Getting started
Authentication & headers
Every request is authenticated with an API key from your dashboard, and every response reports its cost.
Bearer token
Send the key in the Authorization header on every request:
Authorization: Bearer pk_live_…On GET requests only (search, usage, job status and results) you can pass it as the api_key query parameter instead, which is handy for trying search in a browser or downloading batch results. It does not work on POST or DELETE. Prefer the header in code: query strings end up in logs and browser history.
https://api.104-236-84-15.sslip.io/v1/search?q=example&api_key=pk_live_…Managing keys
- Create keys under API keys in the dashboard. A key is
pk_live_(orpk_test_, below) plus 40 letters and digits. The full key is shown exactly once; we store only a SHA-256 hash and a short prefix (likepk_live_AbCd) so you can tell keys apart. - Give each app or environment its own key, so you can revoke one without breaking the others.
- Revoked keys return
401 invalid_api_keywithin a minute (key lookups are cached for up to 60 seconds). - Keep keys server-side. Never ship them in browser or mobile code; anyone with a key can spend your credits.
- Keys belong to the team, not a person. All keys of a team share its credits, rate limit and concurrency.
Live and test keys
Every key has a mode, chosen when you create it and visible in its prefix:
pk_live_…keys fetch real sites, charge credits and count toward your spend limit.pk_test_…keys are free. They never fetch real sites; they return deterministic fake responses marked withx-pageteer-test: 1and"test": true. Validation, blocked targets and rate limits still apply, so a request that works with a test key works with a live one. See Test keys.
Both kinds authenticate the same way and share the team's rate limit and concurrency. A key's mode cannot be changed: create a new key instead.
Requests
- Base URL:
https://api.104-236-84-15.sslip.io/v1. Use HTTPS. POSTbodies are JSON withContent-Type: application/json, at most 64 KB (8 MB forPOST /v1/batch).- The key is checked before the body is read, so a bad key is always a
401, whatever the body. A body that is not a JSON object is415; a known path with the wrong method is405 method_not_allowedwith anAllowheader. - Unknown fields are rejected with
400 invalid_request, so typos never fail silently. Fields such asjs,script,actions,click,form,methodorbodyget a specific message: the API does not run custom JavaScript, submit forms or send non-GET requests to sites. - Timeouts: set your HTTP client's timeout above the request's
timeout_ms(default 30 s, max 120 s). 150 seconds is always enough.
Response headers
| Header | Sent on | Meaning |
|---|---|---|
x-request-id | Every response | A unique id (req_…) for the request. Log it and quote it when you contact support. |
x-credits-used | Every response | Credits this request cost. 0 for errors, cache hits, polling and usage. |
x-credits-remaining | Every response | Free credits left this month after this request: max(0, granted − used). It stays at 0 once you are using billable credits; GET /v1/usage has the full picture. 0 on any response without a valid key. |
x-ratelimit-limit | Authenticated requests | Your requests-per-minute limit. |
x-ratelimit-remaining | Authenticated requests | Requests left in the current window. |
retry-after | Every 429 | Seconds to wait before retrying. |
x-cache | Search; target endpoints that sent max_age | HIT (served from cache, 0 credits), REVALIDATED (the site confirmed the cached copy) or MISS. |
x-cache-age | With x-cache HIT or REVALIDATED | Seconds since the cached copy was fetched or revalidated. |
x-tier-used | Screenshot and PDF | The unblocking tier that produced the capture (the JSON responses carry tier_used instead). |
x-proxy-source | Screenshot and PDF, residential tier | “customer” when your team’s own proxy produced the capture (the JSON responses carry proxy_source). |
x-target-status | Screenshot and PDF as binary | The target site’s HTTP status. |
x-pageteer-test | Requests with a test key | 1: the response is a free fake from a test key (JSON bodies also carry "test": true). Absent on live requests. |
idempotent-replayed | POST /v1/batch and /v1/crawl | true when the response is a replay of an earlier submit with the same Idempotency-Key. |
HTTP/1.1 200 OK
x-request-id: req_2d98773bc3c4412fb509b9964df57976
x-ratelimit-limit: 30
x-ratelimit-remaining: 28
content-type: application/json; charset=utf-8
x-credits-used: 1
x-credits-remaining: 999A missing or bad key returns 401 with {"error":{"code":"invalid_api_key",…}}. See Errors.