- Every scrape spends credits. Only some statuses are charged:
2xxand a target404,400or410cost credits, while429,401(no credits or a suspended subscription), a Scrape.do400,502and510are free. A plain datacenter request is 1 credit; residential proxies and rendering cost more.account.infoandaccount.asyncInfoare free. - A target 404 is a result, not an error.
scrape.htmlreports the target’s status instatus_codeand still returns the page, because the credit was spent. A target410behaves the same way. - 400 means two different things. One is Scrape.do refusing the request (a bad parameter, no credit spent); the other is the target site answering with a bad request (a credit spent). A target’s 400 comes back from
scrape.*as a result withstatus_code: 400, like a 404, so checkstatus_coderather than catching. A Scrape.do refusal throwsScrapeDoAPIErrorwith the provider’s message; itsisTargetRejectionis true only for a 400 that arrived without Scrape.do’s error envelope. - A bad token answers HTTP 200 on
/info. It returnsIsActive: falsewith zeros rather than an error status, soaccount.infoturns that into an error instead of reporting a dead account as healthy. /infois limited to 10 calls a minute and answers429past that. Scrape.do’s own retry mechanism is separate and on by default;disableRetryturns it off.- A screenshot needs the browser and the JSON answer.
scrape.screenshotrequiresrender: trueand always requestsreturnJSON, because the API refuses a screenshot without it. The images come back as base64 PNGs. - Browser-only options are rejected here, not ignored.
waitUntil,customWait,waitSelectorandblockResourcesdo nothing withoutrender, so sending one withrender: falsefails before the request. - The async API is a second host.
jobs.*useshttps://q.scrape.dowith its own concurrency pool and its own account view inaccount.asyncInfo. A job takes up to 100 URLs, and its results are held until they expire, so read them withjobs.resultbefore then.jobs.startdeclares a job, so an agent can read it back withjobs.getinstead of polling the scrape. - Writes are not retried. A POST through the proxy forwards its body to the target site, so a failure is reported rather than replayed: the write may have landed.
- No webhooks. Scrape.do does not send them to this plugin; its own async API can POST results to a URL you set with
webhookUrlat job creation.
- 11 typed API operations
Setup
1
Install
2
Add the plugin
corsair.ts
multiTenancy: true, scope calls with corsair.withTenant(id). See Quick start for KEK + Hub keys, and Multi-tenancy for account isolation.3
Choose authentication
- API Key (Recommended)
No setup required yet. When you make your first request as a tenant, Corsair prompts for the API key.More: API Key
4
Connect a tenant
Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see Connect / OAuth.
Example API calls
Fetch a page as MarkdownWhat’s next
API reference
Every
scrapedo.api.* operation with input and output types.Connect / OAuth
createLink, Hub delivery, and tenant connect flows.
Use with agents
Expose this plugin’s operations as MCP tools.