Docs

01 · Quickstart

Quickstart

You ask a page for something in plain words. You get an answer: the data, how complete it is, and what it cost. One call — with wait, the answer comes back in the same response.

Set me up on Plainscrape: read https://www.plainscrape.com/skills/onboard.md (curl -fsSL it, or open it) and follow it. Do the steps yourself, and only ask me what it tells you to ask.
answer · real run 2026-10-07
{
  "answer_id": "ans_…",
  "state": "ready",
  "shape": "rows",
  "budget": 1,
  "result": [
    {
      "title": "A Light in the Attic",
      "price": 51.77,
      "rating": 3,
      "availability": "In stock",
      "currency": "GBP"
    },
    {
      "title": "Tipping the Velvet",
      "price": 53.74,
      "rating": 1,
      "availability": "In stock",
      "currency": "GBP"
    },
    {
      "title": "Soumission",
      "price": 50.1,
      "rating": 1,
      "availability": "In stock",
      "currency": "GBP"
    }
  ],
  "coverage": {
    "rows": 20,
    "complete": 20,
    "missing": {}
  },
  "receipt": {
    "pages": 1,
    "billed": true
  },
  "sources": [
    "https://books.toscrape.com/"
  ],
  "notes": [],
  "stopped_early": false,
  "error": null,
  "took_s": 4.6
}
20 rows · first 3 shown · coverage: all 20 complete · 1 page billed

No key yet? The Agent tab sets everything up, or get one on the dashboard — 100 free pages, 14 days, free.

02 · Ask

POST /ask

Say what you want in ask. The shape of the answer is read from your words and comes back as shape:

You writeshapeWhat you get
Anything else — “title, price, availability”recordOne record from that page. Always 1 page.
A list — “every book with …”, “top 10 …”, or budget above 1rowsEvery row, following next-page links up to your budget.
A question — “how many books are in the Travel category?”replyReads the start page and follows the links that answer it (up to 20 pages).
FieldNotes
urlrequiredThe page or site, https.
askrequiredPlain words, up to 1,600 characters.
budgetoptionalMost pages this ask may spend — your cost cap. Rows default to 10, a reply to 5 (2 to 20). Trial asks are capped at 10. Above your cap it is trimmed, not refused; budget in the response is what applied.
shapeoptionalrecord, rows or reply — say it when the automatic choice is wrong.
waitoptionalSeconds to hold the call for the answer, up to 60. Ready in time: 200 and the answer. Otherwise 202, state: "working" and check, the URL to look at.
callback_urloptionalA public https URL. Once the answer is ready we POST it there, the same JSON GET /answers/{answer_id} returns, exactly once. A 5xx or no reply is retried three times; redirects are not followed. For Zapier, Make and your own webhooks.
networkoptional"residential" goes out through home-broadband IPs, for sites that turn datacentres away. Same price.
countryoptionalExit country (ISO code, e.g. de) for rows on the residential network.

A record

ask(url="https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", ask="title, price, rating, availability")
answer · real run 2026-10-07
{
  "answer_id": "ans_…",
  "state": "ready",
  "shape": "record",
  "budget": 1,
  "result": {
    "title": "A Light in the Attic",
    "price": 51.77,
    "rating": 3,
    "availability": "In stock (22 available)"
  },
  "coverage": {
    "rows": 1,
    "complete": 1,
    "missing": {}
  },
  "receipt": {
    "pages": 1,
    "billed": true
  },
  "sources": [
    "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
  ],
  "notes": [],
  "stopped_early": false,
  "error": null,
  "took_s": 2.7
}
a field list on one page is one record · 1 page billed

Asked one page for a list without saying “every”? notes tells you to say “every …” to get separate rows.

Rows, across pages

ask(url="https://books.toscrape.com/", ask="every book with title, price, rating and availability", budget=1)
answer · real run 2026-10-07
{
  "answer_id": "ans_…",
  "state": "ready",
  "shape": "rows",
  "budget": 1,
  "result": [
    {
      "title": "A Light in the Attic",
      "price": 51.77,
      "rating": 3,
      "availability": "In stock",
      "currency": "GBP"
    },
    {
      "title": "Tipping the Velvet",
      "price": 53.74,
      "rating": 1,
      "availability": "In stock",
      "currency": "GBP"
    },
    {
      "title": "Soumission",
      "price": 50.1,
      "rating": 1,
      "availability": "In stock",
      "currency": "GBP"
    }
  ],
  "coverage": {
    "rows": 20,
    "complete": 20,
    "missing": {}
  },
  "receipt": {
    "pages": 1,
    "billed": true
  },
  "sources": [
    "https://books.toscrape.com/"
  ],
  "notes": [],
  "stopped_early": false,
  "error": null,
  "took_s": 4.6
}
20 rows · first 3 shown · raise budget to follow next pages

A reply about a site

ask(url="https://books.toscrape.com/", ask="How many books are in the Travel category?", budget=3)
answer · real run 2026-10-07
{
  "answer_id": "ans_…",
  "state": "ready",
  "shape": "reply",
  "budget": 3,
  "result": {
    "travel_category_book_count": 11
  },
  "coverage": null,
  "receipt": {
    "pages": 2,
    "billed": true
  },
  "sources": [
    "https://books.toscrape.com/catalogue/category/books/travel_2/index.html"
  ],
  "notes": [],
  "stopped_early": false,
  "error": null,
  "took_s": 16.0
}
read 2 pages of the 3 allowed · sources lists the pages it read
03 · The answer

GET /answers/{answer_id}

Without wait (or when an answer outlasts it), check GET /answers/{answer_id} every 2 seconds while state is working, or pass callback_url and we post the answer to you when it is ready. Typical times: about 8 seconds for a record and 20–30 for a reply. Rows take 30–60 seconds the first time we see a site, while we work out how to read it, and 5–15 seconds on later asks. Long lists can take a few minutes; an answer is capped at 12 minutes and returns what it has.

FieldMeaning
stateworking, ready, failed or expired.
resultThe data: an object for a record or a reply, a list for rows. Prices and ratings are numbers; rows add currency when the page shows one. Rows are read straight from the page by code that runs on it; a value the page doesn't have comes back empty.
coverageHow complete the rows are: rows, rows with every field filled (complete), and how many rows lack each field (missing).
receiptWhat this answer cost: pages billed, billed, and pages_left on the account. One page fetched is one page; failed pages are free.
sourcesThe pages the answer was read from.
notesPlain sentences worth knowing: a filter that couldn't apply, a page that was too long, rows left out to fit the size cap.
stopped_earlytrue when the time cap or a failed page ended it after rows came back; you get those rows and pay only for pages read.
errorOn failed: what happened, what to do, and whether it cost anything — see errors.
took_sHow long it took. Answers are kept 24 hours; over MCP, ready answers also carry download_url, the whole answer as a JSON file at GET /answers/{answer_id}/file (send your key).
04 · Account

GET /account

Plan, pages left, limits and the answers still working. MCP: account().

account · trial
{
  "email": "you@example.com",
  "plan": "trial",
  "pages": {
    "left": 76,
    "used_this_period": 24,
    "period_start": "2026-10-01T00:00:00Z",
    "plan_pages": 0,
    "trial_pages": 100,
    "trial_ended": false
  },
  "subscription": null,
  "upgrade_url": "https://www.plainscrape.com/app",
  "limits": {
    "budget_max": 10,
    "reply_budget_max": 20,
    "asks_per_minute": 15,
    "checks_per_minute": 60,
    "working_at_once": 3,
    "result_bytes_max": 5000000,
    "wait_max_s": 60
  },
  "working": []
}
on a plan, subscription shows the renewal date and rollover

Plans, top-ups and cancelling are on the dashboard; see pricing.

05 · Keys

Keys, and letting an agent get one

Send x-api-key: ps_live_… on every request. A missing or wrong key is refused before anything starts, so it never costs pages. Get a key on the dashboard, or let an agent do it in two calls:

curl -X POST https://www.plainscrape.com/agent/signup -H "Content-Type: application/json" \
  -d '{"email":"you@company.com"}'
# → { "session_id": "…", "message": "A 6-digit code is on its way to you@company.com.", "expires_in_s": 900 }

curl -X POST https://www.plainscrape.com/agent/claim -H "Content-Type: application/json" \
  -d '{"code":"123456","session_id":"…"}'
# → { "api_key": "ps_live_…", "key_prefix": "ps_live_…", "mcp_config": {…}, "pages_left": 100, "trial_ends_at": "…" }

A code works once, for 15 minutes; five wrong codes end the session. The key is shown once — make a new one on the dashboard if you lose it.

06 · Errors

Errors your agent can act on

Every error says what happened, what to do next, whether it cost anything, and whether trying again makes sense. A failed answer has the same error object inside it, with state: "failed".

402 · out of pages
{
  "error": {
    "code": "out_of_pages",
    "message": "You've used all 2,000 pages on your Starter plan this month. Add pages or upgrade at https://www.plainscrape.com/app — both take effect right after payment — or wait until your plan renews on 2026-11-04.",
    "fix": "Add pages or upgrade at upgrade_url.",
    "billed": false,
    "retry": false,
    "pages_left": 0,
    "pages_asked": 5,
    "upgrade_url": "https://www.plainscrape.com/app",
    "docs": "https://www.plainscrape.com/docs#errors-out-of-pages"
  }
}
codeWhat it means, what to do
page_unreadableanswerThe page could not be read (blocked, empty or unreachable). Failed pages are free and don't stop the rest of the answer. If the site turns datacentres away, ask again with network: "residential".
page_not_foundanswerThe site showed a "not found" page for that address. Check that the URL opens the page you mean in a browser. Nothing billed.
nothing_foundanswerNothing on the page matched your ask. Name the fields you want, or check the URL.
nothing_usableanswerThe answer came back empty. Name the fields more specifically and ask again. Nothing billed.
too_slowanswerThe answer took too long and was stopped; nothing billed. A long list that runs out of time after returning rows comes back ready with stopped_early: true instead, billed for the pages read.
residential_unavailableanswerYou asked for network: "residential" and it is unavailable right now. Ask without it, or in a few minutes.
not_started / never_finishedanswerThe ask couldn't start, or never finished. Nothing charged; ask again.
answer_expiredanswerAnswers are kept 24 hours. After that state is expired and result is null; the receipt keeps what was billed. The saved copy stays downloadable from the dashboard.
address_not_public422The URL isn't a public web page (a private or internal address). Nothing was fetched.
site_not_supported403The site's terms forbid scraping (LinkedIn, Yelp, Zillow). Use its official API.
bad_request422A field is missing or isn't one we take. message says which, in a sentence; fields lists them.
ask_too_long400The ask is over 1,600 characters. Nothing reserved or billed.
out_of_pages402No pages left. message names your plan and renewal date; upgrade_url is where a person adds pages. A budget above what's left is trimmed to what's left, not refused.
answer_not_found404Unknown answer id, or one that isn't yours — both look the same.
too_many_working429This account already has the most answers working at once. working lists them; a slot frees as soon as one is ready.
slow_down429Too many requests in the window. Wait retry_in_s. Checking answers you already asked for is a separate window, so it keeps working.
paused503Asks are paused on our side for a moment; your request is fine. Nothing created. Retry in a few seconds.
missing_key / unknown_key401Send x-api-key, or create a new key on the dashboard.
07 · Limits

Limits

Asks and working answers are counted per account — a second key doesn't buy a second window. Checks are per key and separate, so waiting on a slow answer never uses up the next ask.

LimitTrialStarterWhat it counts
Asks15 / min60 / minPOST /ask, across every key on the account.
Checks60 / min600 / minGET /answers/… and /account. Sized for checking every 2 seconds; wait doesn't use them.
Working at once310Answers asked but not yet ready, across the account.
Budget per ask10No capA reply reads at most 20 pages on every plan. Higher values are trimmed, not refused.
Ask length1,600 characters1,600Over it: ask_too_long, nothing billed.
Result size5 MB5 MBBeyond it, rows are dropped from the end and notes says how many.

Every response carries the window in the standard RateLimit fields; a 429 adds Retry-After:

RateLimit: limit=15, remaining=14, reset=42
RateLimit-Policy: 15;w=60
Retry-After: 42
reset is seconds until a slot frees up · the window slides, so a burst doesn't reset on a clock boundary

Upgrading raises these; GET /account always shows yours. Tell us what you're building.

08 · MCP

MCP

Three tools at https://www.plainscrape.com/mcp: ask, answer, account — the same answer object as the REST API. ask waits up to about 45 seconds, so most answers come back in one call. Add the URL with no key and your client opens a browser tab to sign in (OAuth 2.1 with PKCE); approve once. Clients without sign-in send x-api-key. Setup for each client: MCP page, or Connect at the top.

~/.cursor/mcp.json
{
  "mcpServers": {
    "plainscrape": {
      "url": "https://www.plainscrape.com/mcp",
      "headers": {
        "x-api-key": "ps_live_YOUR_KEY"
      }
    }
  }
}

On the roadmap

Recipes — rerun what worked on a site, on any of its pages, faster — and watches: scheduled asks that tell you what changed. Today, ask again or check /answers.