Troubleshooting
Common errors you may hit, what they mean, and how to fix them.
Authentication
401 Unauthorized — Invalid or missing API key
The fail-closed policy is at work:
PRY_API_KEYset → every request needsAuthorization: Bearer <key>. Add the header, or generate a key withpython -c "import secrets; print(secrets.token_urlsafe(48))".PRY_API_KEYunset → only loopback (127.0.0.1/::1) is allowed. If you're calling from another host, either set a key or run the request from the host machine.
Proxy/Tor config endpoints (/v1/proxy/configure, POST /v1/config,
/v1/config/profile/tor) are guarded in addition to the middleware —
remote clients must present the key.
Rate limiting
429 Too Many Requests — Rate limit exceeded
Default limit is 120 requests/minute per IP (PRY_RATE_LIMIT_RPM). The
response includes Retry-After and x-ratelimit-* headers.
Fixes:
- Back off: respect
Retry-After. - Raise the limit: set
PRY_RATE_LIMIT_RPMhigher (and restart). - Distribute load: batch work through
/v1/batch(up to 50 URLs per call).
Cloudflare / blocking
Scrape returns HTML with a Cloudflare challenge
Check which tier succeeded:
curl -X POST http://localhost:8005/v1/ultimate-scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://challenged.example.com"}'
# look at method_used in the response
- If
method_usedisdirect, the site is likely fine without bypass. - If challenges persist, verify FlareSolverr is healthy:
docker compose ps— thepryservice waits forflaresolverrto be healthy before starting. - Use
POST /v1/detect-blockto identify the vendor (Cloudflare, DataDome, …) and confidence. - Enable the stealth stack (
PRY_STEALTH_ENABLED=true) and residential proxies (WEBSHARE_PROXY_LIST) for aggressive WAFs.
POST /v1/detect-block — what does the response mean?
It returns the detected protection tier, vendor, and confidence. Use it to decide whether to invest in proxies, browser tiers, or a different source for the data.
Ports & connectivity
Connection refused on http://localhost:8005
- Docker publishes host 8005 → container 8002. From the host, use
8005. - Port
8002is only reachable if youdocker execinto the container. - Check the service is up:
docker compose psandcurl -fsS http://localhost:8005/health.
Health check fails in Docker
The container healthcheck probes http://localhost:8002/health (container
port). If the app crashes at startup (bad .env, missing secrets), the
container never becomes healthy. Check logs:
docker logs pry --tail 100 -f
Tor
Tor tier errors with missing aiohttp-socks
The Tor routing tier is documented but currently disabled in some installs —
aiohttp-socks is missing from dependencies. Either install it
(pip install aiohttp-socks), enable the tor compose profile, or let the
fallback chain skip the Tor tier (it continues to the archive tiers).
x402 payments
402 Payment Required on every call
x402 gating is enabled (PRY_X402_ENABLED=true) and you haven't paid. Either:
- Complete the flow: pay the wallet from the
PAYMENT-REQUIREDheader, thenPOST /v1/x402/paywith thetx_hash, and send the returnedpayment_idasX-Payment-Id. - Disable gating (
PRY_X402_ENABLED=false) if you didn't intend to charge.
underpayment: client supplied X USD, server requires Y USD
The server enforces the authoritative price (validate_client_amount). Send
at least the listed price from GET /v1/x402/pricing for the operation.
Payment verifies but the endpoint still 402s
Check PRY_X402_PAYMENT_TTL (default 3600s) — the payment_id expires and
must be re-paid. Also confirm you're sending the X-Payment-Id header
(case-insensitive) on the paid call.
PRY_X402_OFFLINE=true is ignored
Offline (dev-only) mode requires DEBUG=true or PRY_DEBUG=true as a second
gate. It's intentional — never run offline verification in production.
Migrations
Container won't start — Alembic error
The entrypoint runs alembic stamp head (idempotent), falling back to
alembic upgrade head on failure. If a migration is genuinely broken:
docker exec pry alembic current
docker exec pry alembic upgrade head
Use PRY_SKIP_MIGRATIONS=1 only for read-only debug runs.
Common response-shape gotchas
422 Validation Error
Pydantic rejected the body. Check the documented fields (e.g. url is
required on /v1/scrape, steps is required on /v1/automate, schema is
required on /v1/extract/css). The error response includes field-level
details.
Error format
All errors are RFC 7807 Problem Details with type, title, status,
detail, request_id, instance, timestamp, code. Match on code or
status, and log request_id for correlation — see
API Overview → Error format.
Still stuck?
GET /health— health + cache stats + active sessionsGET /metrics— Prometheus metrics- Open an issue at git.rugmunch.io/RugMunchMedia/pryscraper
- Commercial support: [email protected]