API Overview
Pry exposes a FastAPI JSON API. All endpoints are documented in the bundled
OpenAPI spec (openapi.json in the repo root) and served live at
/docs (Swagger UI) when the server is running.
Base URL
| Environment | Base URL |
|---|---|
| Local (bare metal) | http://localhost:8002 |
| Docker (host) | http://localhost:8005 |
| Configurable | PRY_URL env var |
All request/response bodies are JSON. There are 188 registered paths across 46 tag groups.
Authentication
Authentication is enforced by the PryHttpMiddleware and request_authorized.
The policy is fail-closed:
PRY_API_KEYset → EVERY request (loopback or remote) must sendAuthorization: Bearer <key>(or an rmi JWT). Requests without a valid credential get401 Unauthorized.PRY_API_KEYunset → the API is only reachable from the loopback interface (127.0.0.1/::1). Every non-loopback request is rejected with401, so a keyless instance is never exposed to the internet (e.g. when the Docker port mapping is public).
curl -X POST http://localhost:8005/v1/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-key>" \
-d '{"url": "https://example.com"}'
Public paths that skip auth: /health, /live, /ready (liveness/readiness
probes).
Proxy/Tor configuration endpoints (/v1/proxy/configure, POST /v1/config,
/v1/config/profile/tor) are additionally guarded: remote clients that cannot
present the key are rejected.
Rate limits
- Token bucket per IP, default 120 requests/minute (
PRY_RATE_LIMIT_RPM). - Exceeding the limit returns
429 Too Many Requestswith:Retry-Afterresponse header (seconds)x-ratelimit-limit,x-ratelimit-remaining,x-ratelimit-resetheaders- A body containing
retry_after
{
"type": "/errors/rate_limit_exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded",
"request_id": "a1b2c3d4e5f6",
"instance": "/v1/scrape",
"timestamp": "2026-08-16T12:00:00.000000+00:00",
"code": "rate_limit_exceeded",
"retry_after": 1
}
Error format
Errors follow RFC 7807 Problem Details, returned by the global exception handler:
{
"type": "/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid or missing API key",
"request_id": "a1b2c3d4e5f6",
"instance": "http://localhost:8005/v1/scrape",
"timestamp": "2026-08-16T12:00:00.000000+00:00",
"code": "unauthorized"
}
| Field | Meaning |
|---|---|
type | Error type URI (/errors/<slug>, or about:blank for 500s) |
title | Human-readable title |
status | HTTP status code |
detail | Human-readable detail |
request_id | Correlation ID (also echoed in the x-request-id response header) |
instance | The request URL that produced the error |
timestamp | ISO 8601 UTC timestamp |
code | Machine-readable slug of the error |
Common status codes:
| Code | Meaning |
|---|---|
400 | Bad request (invalid input) |
401 | Unauthorized — missing/invalid API key, or remote client with no key set |
403 | Forbidden |
404 | Not found (unknown path) |
409 | Conflict |
422 | Validation error (Pydantic) |
429 | Rate limit exceeded |
500 | Internal server error (detail is hidden, use request_id) |
502 / 503 | Upstream / service unavailable |
402 | Payment required — only when x402 gating is enabled (see x402 Pay-per-call) |
Health & monitoring endpoints
| Endpoint | Purpose |
|---|---|
GET /health | Service health + cache stats + active sessions |
GET /live | Liveness probe |
GET /ready | Readiness probe |
GET /metrics | Prometheus metrics |
GET /v0/stats | Basic stats |
Request IDs
Every request gets a request_id. Send your own with the x-request-id
header to correlate logs end-to-end; otherwise a UUID is generated.
API groups
The API is organized into tag groups — the most relevant for day-to-day use:
| Tag | Key endpoints |
|---|---|
| Health | /health, /live, /ready |
| Scraping | /v1/scrape, /v1/crawl, /v1/map, /v1/batch, /v1/ultimate-scrape, /v1/detect-block |
| Extraction | /v1/extract, /v1/extract/css, /v1/extract/llm, /v1/parse, /v1/shadow-dom, /v1/schema |
| Automation | /v1/automate, /v1/screenshot, /v1/session/*, /v1/capture/* |
| x402 | /v1/x402/pricing, /v1/x402/pay, /v1/x402/verify, /v1/x402/payment, /v1/x402/require-payment |
| Batch | /v1/batch, /v1/batch-file |
| Monitoring | /v1/watch, /v1/monitor, /v1/freshness/*, /v1/diff |
| Analysis | /v1/vision, /v1/summarize, /v1/categorize, /v1/compare |
| Sessions | /v1/session/create, /v1/session/save, /v1/session/restore, /v1/session/destroy, /v1/sessions |
| MCP | /mcp/tools, /mcp/call (see MCP Integration for the supported transports) |
Next steps
- Scraping API — scrape, crawl, batch, map, ultimate-scrape
- Extraction API — CSS/LLM extraction, parse, shadow DOM
- Automation API — automate, sessions, capture