Skip to content
Docs menu

Browser API

PDF

Print a page to PDF in a real browser.

POST https://api.104-236-84-15.sslip.io/v1/pdf

Body parameters

PDF parameters
NameTypeDescription
urlrequiredstring (≤ 2048 chars)Absolute http:// or https:// URL. No embedded credentials, no private or internal hosts.
format"A4" | "Letter"Paper size. Default: "A4".
print_backgroundbooleanInclude background colors and images. Default: false.
unblock"none" | "stealth" | "residential" | "auto"Unblocking tier. residential goes through your team's own proxy. auto escalates none → stealth → residential (when your team has a proxy) and charges only for the tier that succeeded. See Unblocking tiers. Default: "none".
timeout_msinteger (1000–120000)Time budget for the whole request, shared by every unblock tier tried. Running out returns 504 timeout (not charged). Default: 30000.
max_ageinteger (seconds, 0–86400)Opt-in cache. If your account made the same request (same URL and options) within max_age seconds, you get that response back without us contacting the site, for 0 credits. An older copy is revalidated with a conditional request when the site supports it. 0 always fetches but stores the result. Omit it and the cache is not used. See Render → Caching.
respect_robotsbooleanCheck the site’s robots.txt (user agent PageteerBot) first. A disallowed URL fails with 403 robots_disallowed and is not charged; a Crawl-delay spaces our requests to that site. Default: false.
actionsobject[] (≤ 20)Read-only page actions run in the browser after the page loads: wait, wait_for, scroll, click ("Load more", tabs, accordions), press and screenshot. Forces a browser render. No typing, form submission or logins. See Page actions.

Example

curl
curl -X POST https://api.104-236-84-15.sslip.io/v1/pdf \
  -H "Authorization: Bearer $PAGETEER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","format":"Letter","print_background":true}' \
  -o example.pdf
JavaScript (fetch)
const res = await fetch('https://api.104-236-84-15.sslip.io/v1/pdf', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PAGETEER_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "url": "https://example.com",
    "format": "Letter",
    "print_background": true
  }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('example.pdf', bytes));
Python (requests)
import os
import requests

headers = {"Authorization": f"Bearer {os.environ['PAGETEER_API_KEY']}"}
res = requests.post(
    "https://api.104-236-84-15.sslip.io/v1/pdf",
    headers=headers,
    json={
        "url": "https://example.com",
        "format": "Letter",
        "print_background": True,
    },
    timeout=120,
)
res.raise_for_status()
with open("example.pdf", "wb") as f:
    f.write(res.content)

Response

The body is the PDF (application/pdf), with these headers:

200 OK
content-type: application/pdf
x-request-id: req_f44ed10e9c024ecdae615147b2d35316
x-tier-used: none
x-target-status: 200
x-credits-used: 5
x-credits-remaining: 968
content-length: 26393

Send Accept: application/json for JSON instead: the same fields as a JSON screenshot (url, final_url, status, content_type, tier_used, attempts, cached, credits) with the document in pdf_base64.

Credits

5 credits, plus the tier that succeeded (stealth +5, residential through your own proxy +0). A target 5xx is printed but not charged; cache hits cost 0.

Errors

PDF errors
StatusCodeWhenChargedWhat to do
400invalid_requestA parameter is missing, invalid or unknown (the message and error.issues name it).NoFix the request; retrying it unchanged fails again.
401invalid_api_keyNo key, an unknown key, or a revoked or expired key.NoCheck the Authorization header and the key on the API keys page.
402insufficient_creditsNot enough credits left this month for this request, and billable usage is off. error.reason says why: free_credits_used, payment_failed or subscription_inactive.NoAct on the reason at error.billing_url: add a card, update the payment method, or restart the subscription. Or wait for the 1st (UTC).
402spend_limit_reachedBillable usage is on and this month’s spend limit is reached (error.reason: spend_limit).NoRaise the spend limit at error.billing_url (the Billing page), or wait for the 1st (UTC).
403forbidden_targetThe URL is denylisted, resolves (or redirects) to a private or internal address, or sends cookies or credentials to a login, account or checkout page.NoDo not retry. See the Acceptable Use Policy.
403robots_disallowedrespect_robots is on (default for crawl and batch) and the site’s robots.txt disallows the URL for PageteerBot.NoSkip the URL. Turn respect_robots off only for sites you own or may crawl.
403org_suspendedThe account is suspended.NoContact support.
403feature_not_in_planSchema extraction on the free mode or while it is not available on this deployment.NoUse selectors or structured, or add a card.
403proxy_not_configuredunblock "residential" without a team proxy saved in Settings → Proxy (404 from POST /v1/proxy/test).NoSave your proxy URL in Settings → Proxy (see Bring your own proxy), or use another tier.
413payload_too_largeThe request body is over 64 KB (8 MB for POST /v1/batch), or a crawl is too large to export in one file.NoSend less, or split a batch; read a large crawl with GET /v1/crawl/:id.
422target_blockedThe site blocked every tier we tried (with unblock "auto", the tiers this deployment offers). block_reason, block_vendor and attempts say how.NoTry a stronger unblock tier (or "auto"); if auto already failed, retry much later.
422captcha_requiredThe site answered with a CAPTCHA or bot challenge. We never solve them and try no further tier.NoDo not retry soon. Use the site’s API or data feed if it has one.
422login_requiredThe site redirected to a login or sign-in page (final_url says where). We never log in.NoThe content is not public: skip it.
429rate_limitedOver your requests per minute, or too many requests to one site across the platform right now.NoWait Retry-After seconds, then back off with jitter.
429concurrency_limitToo many of your requests are in flight at once.NoWait for one to finish (Retry-After: 1) or lower your parallelism.
429target_rate_limitedThe site asked us to slow down (429, or 503 with Retry-After), or per-site pacing would not let your request start in time. We pause that site for everyone.NoWait error.retry_after seconds (also in Retry-After).
502proxy_failedYour proxy failed: reason "auth" (it rejected the credentials), "unreachable", "status" (it refused the connection) or "blocked" (its host resolves to a private address).NoFix the URL or credentials in Settings → Proxy and test it. "unreachable" and "status" may pass on retry.
500 / 502 / 503internal_errorSomething failed on our side (rendering engine, LLM extraction or the API itself), or the rendering engine is at capacity (503, Retry-After: 5).NoRetry with backoff (honor Retry-After); quote x-request-id if it persists.
504timeoutThe site did not answer within timeout_ms.NoRetry, maybe with a larger timeout_ms or mode "http".