extraction_failed
HTTP 422 · not billed
{ "error": {
"code": "extraction_failed",
"message": "…",
"docs_url": "https://pdfcraft.dev/errors#extraction_failed"
} }When you get it
The PDF parsed but carries no text layer, so there is nothing to extract. Usually a scan or a photo.
The PDF opened and parsed, and carries no text layer to read. Usually a scan or a photograph of a document rather than a document.
How to fix it
- Check pages_without_text in the response — it names exactly which pages were blank.
- Route those pages to something that does OCR. This endpoint does not, and returning quickly is more useful than returning a guess.
Is it billed?
No. A request is billed only when Chromium actually ran. NOT billed, unlike render_failed, and the difference is deliberate: detecting a missing text layer costs about 20 ms a page and returns nothing of value. Charging for a "no" is how a feature earns refund requests.
Reproducing it
curl -i -X POST https://api.pdfcraft.dev/v1/render \
-H "Authorization: Bearer $PDFCRAFT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>hi</h1>"}'The -i matters: Retry-After and X-Renders-Remaining are headers, and a client that only reads the body throws away the two numbers that tell it what to do next.
Every code
| HTTP | Code | Billed? |
|---|---|---|
| 400 | invalid_request | free |
| 401 | invalid_api_key | free |
| 402 | payment_required | free |
| 404 | not_found | free |
| 408 | render_timeout | free |
| 422 | render_failed | billed |
| 429 | rate_limited | free |
| 429 | quota_exceeded | free |
| 429 | demo_busy | free |
| 415 | unsupported_file | free |
| 422 | extraction_failed | free |
| 500 | internal_error | free |