Start with your API key
Create an account, verify your email, then create a ProtoScrape API key. Store it in your server’s PROTOSCRAPE_API_KEY environment variable or secret manager. The same key works with every library and engine. Keep it out of browser bundles and source control.
These are versioned downloads hosted by ProtoScrape. No GitHub access is required. Use the URLs below; this release is not listed on npm, PyPI or Packagist. All clients use the same public API, with no third-party runtime dependencies beyond each language’s standard HTTP support.
Download SHA-256 checksums · Release manifest · OpenAPI specification
| Engine | API identifier | Credits per success |
|---|---|---|
| Google Search | google_serp | 1 |
| Google AI Mode | google_ai_mode | 5 |
| ChatGPT | chatgpt | 8 |
| Perplexity | perplexity | 4 |
Current coverage is US, English, desktop. Check the engine catalog before submitting. Availability varies by query and platform.
Node.js & TypeScript
Node.js 20+; ESM and CommonJS. TypeScript declarations included.
npm install https://protoscrape.com/sdk/v0.2.0/protoscrape-client-0.2.0.tgzimport {ProtoScrape, JobFailedError} from '@protoscrape/client';
const client = new ProtoScrape();
const job = await client.submit(
{engine: 'google_serp', query: 'What is the capital of France?'},
{idempotencyKey: 'your-persisted-request-id'}
);
// Save job.id before waiting.
try {
await client.wait(job.id);
console.log((await client.getResult(job.id)).data);
} catch (error) {
if (error instanceof JobFailedError) console.log(error.job.status);
else throw error;
}CommonJS: const {ProtoScrape} = require("@protoscrape/client");. Use APIError for HTTP errors and WaitTimeoutError.jobId to resume after a local wait timeout. Submission errors retain idempotencyKey. Node supports an AbortSignal on submit and wait.
Python
Python 3.10+. Install into a virtual environment.
python -m pip install https://protoscrape.com/sdk/v0.2.0/protoscrape-0.2.0-py3-none-any.whlfrom protoscrape import ProtoScrape, JobFailedError
client = ProtoScrape()
job = client.submit('chatgpt', 'What is the capital of France?',
idempotency_key='your-persisted-request-id')
# Save job['id'] before waiting.
try:
client.wait(job['id'])
print(client.get_result(job['id'])['data'])
except JobFailedError as error:
print(error.job['status'])The Python client is synchronous. Use a background worker for long-running jobs. APIError exposes status, code, request_id, retry_after and idempotency_key; wait errors retain job_id.
Go
Go 1.22+. Run the install command inside your Go module.
GOPROXY=https://protoscrape.com/sdk/go \
GONOSUMDB=github.com/protostar0/protoscrape-sdks/go \
go get github.com/protostar0/protoscrape-sdks/go@v0.2.0package main
import (
"context"
"log"
"os"
ps "github.com/protostar0/protoscrape-sdks/go"
)
func main() {
client, err := ps.New(os.Getenv("PROTOSCRAPE_API_KEY"))
if err != nil { log.Fatal(err) }
ctx := context.Background()
job, err := client.Submit(ctx, ps.Input{
Engine: ps.Perplexity,
Query: "Explain three benefits of solar energy.",
}, ps.SubmitOptions{IdempotencyKey: "your-persisted-request-id"})
if err != nil { log.Fatal(err) }
// Save job.ID before waiting.
if _, err = client.Wait(ctx, job.ID, ps.WaitOptions{}); err != nil {
log.Fatal(err)
}
result, err := client.GetResult(ctx, job.ID)
if err != nil { log.Fatal(err) }
log.Print(result.Data.AnswerText)
}The module is served by ProtoScrape’s module proxy. The environment settings above apply to that command only. Keep your application’s go.sum; use the same proxy and checksum-database exception for clean installs of this module. Our SHA-256 manifest also covers the module archive. Use errors.As with *APIError, *JobFailedError or *WaitTimeoutError for error handling.
PHP
PHP 8.2+ with the cURL and JSON extensions.
curl -fL https://protoscrape.com/sdk/v0.2.0/protoscrape-php-0.2.0.zip -o protoscrape.zip
unzip protoscrape.zip -d vendor/protoscrape<?php
require __DIR__ . '/vendor/protoscrape/src/Client.php';
$client = new \ProtoScrape\Client();
$job = $client->submit(
['engine' => 'google_ai_mode', 'query' => 'What is the capital of France?'],
['idempotency_key' => 'your-persisted-request-id']
);
// Save $job['id'] before waiting.
try {
$client->wait($job['id']);
echo $client->getResult($job['id'])['data']['answer_text'];
} catch (\ProtoScrape\JobFailedError $error) {
echo $error->job['status'];
}Run longer jobs in a background worker. Composer users can register the extracted package as a path repository for protoscrape/client. APIError exposes status, errorCode, requestId, retryAfter, idempotencyKey and jobId where applicable.
Everything you need to follow a job
Every client includes submission, polling, result retrieval, cancellation, paginated history, batch status, the engine catalog, account limits and credit usage. The scrape helper combines submit, wait and result retrieval. Each downloaded package includes a README with method names, options and error types.
| Operation | Node / PHP | Python | Go |
|---|---|---|---|
| Submit | submit | submit | Submit |
| Wait | wait | wait | Wait |
| Read result | getResult | get_result | GetResult |
| Cancel | cancel | cancel | Cancel |
| Batch status | statuses | statuses | Statuses |
| Usage | usage | usage | Usage |
Durable batches
Save up to 100 inputs in one batch, with optional tags and a maximum credit quote. Pending inputs reserve no credits; jobs are admitted when capacity and credits are available. Pending inputs expire after 24 hours, even while paused. Use the batch guide for limits and lifecycle details.
const batch = await client.createBatch({
name: 'Weekly observation', max_credits: 9,
items: [
{engine: 'google_serp', query: 'Project management tools', tag: 'tools'},
{engine: 'chatgpt', query: 'Compare project management tools', tag: 'tools'}
]
}, {idempotencyKey: 'your-persisted-batch-id'});
// Save batch.id. Inspect later; no long-running SDK wait is required.
console.log(await client.getBatch(batch.id));| Operation | Node / PHP | Python | Go |
|---|---|---|---|
| Create batch | createBatch | create_batch | CreateBatch |
| Inspect batch | getBatch | get_batch | GetBatch |
| List batches | listBatches | list_batches | ListBatches |
| Pause / resume | pauseBatch / resumeBatch | pause_batch / resume_batch | PauseBatch / ResumeBatch |
| Cancel remaining | cancelBatch | cancel_batch | CancelBatch |
Python: client.create_batch(items, name="Report", max_credits=9, idempotency_key="saved-id"). PHP: $client->createBatch($input, 'saved-id'). Go: client.CreateBatch(ctx, ps.BatchInput{Items: items, MaxCredits: "e}, "saved-id"), where items is []ps.BatchItemInput. Downloaded READMEs include complete examples. Poll a batch every 20 seconds or longer, within account rate limits. Cancellation keeps already-completed successful charges.
Failed jobs cost zero credits
Submitting an accepted job temporarily reserves its credits. A successful job charges those credits exactly once. A failed, expired or cancelled job charges zero and returns its reservation. An invalid request rejected before admission reserves nothing. Reading an existing result does not create a new charge.
A local timeout or abort does not cancel the server job. It may still succeed and charge normally. Save the job ID and resume checking it, or call cancel explicitly. Cancellation cannot reverse a job that already succeeded. The SDKs raise a job-failure error for a non-success terminal state; they never create replacement jobs automatically.
Retry safely
Save a unique idempotency key for each logical request. Reuse the same key and identical input after an uncertain submission. SDK-generated keys protect automatic HTTP retries, but application restarts need your saved key. A new call without that key creates a separate job.
Clients retry transient network errors and HTTP 408, 429, 500, 502, 503 and 504 up to twice by default, reusing the original submission key. Other client errors return immediately. Retry-After is respected; delays above the default 60-second limit return to your application. Keep error request IDs when contacting support.
Build a bounded queue
Default HTTP timeout: 30 seconds. Default wait limit: 31 minutes. Polling backs off from 5 to 20 seconds. Server jobs have a 30-minute deadline. For many active jobs, use batch status with up to 50 IDs instead of starting a separate poll loop for each job.
The current API limit is 120 requests/minute per tenant, with 30 submission requests/minute and account-specific job concurrency. Use durable batches for up to 100 inputs at a time; keep excess inputs beyond the account pending limit in your own queue. Results are retained for approximately seven days; save results you need longer. Idempotency records remain for 30 days. Batch submission is available through the methods above. Customer callback webhooks and recurring schedules remain planned features.
Need help? Contact support with a job or request ID. Never share your full API key. Support hours: Monday–Friday, 09:00–18:00 Europe/Paris; first human response target: one business day.