Document OCR
Upload a PDF, run OCR, and get extracted text or a searchable PDF back. Five requests from file to result.
How does the FastOCR Document OCR API work?
The FastOCR Document OCR API enables programmatic text extraction and searchable PDF generation from scanned documents and images up to 1 GB in size. Using state-of-the-art vision models, the service recognizes complex multi-column typography across 100+ languages including Arabic, Chinese, Cyrillic, Devanagari, Japanese, Korean, and Latin scripts. Integration follows a predictable asynchronous REST workflow: submit a POST request with an idempotency key to receive a presigned S3 upload URL, upload the file directly, trigger extraction, poll job status, and retrieve results in plain text or searchable PDF format. With per-page billing quotas and concurrency-controlled workers, the API supports both real-time single-page processing and large-scale batch archive digitalization.
Quickstart
Create a job, upload the PDF, start processing, poll for completion, and download the result.
Python SDK (Recommended)
# Install official SDK:
# pip install fastocr
from fastocr import FastOCR
client = FastOCR(api_key="your-api-key")
# 1. Extract raw text for RAG chunking in one line:
raw_text = client.extract_text("scan.pdf")
print(raw_text)
# 2. Or generate and save a searchable PDF with text overlay:
job = client.documents.process("scan.pdf")
client.documents.download_searchable_pdf(job.id, "searchable_output.pdf")cURL / REST
FASTOCR_KEY="your-api-key"
# 1. Create a document job
curl -s -X POST https://api.fastocr.org/v1/documents \
-H "Authorization: Bearer $FASTOCR_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"filename":"scan.pdf","size_bytes":'$(wc -c < scan.pdf | tr -d ' ')'}'
# 2. Upload the file to the presigned URL (from step 1 response)
curl -s -X PUT "<upload_url>" \
-H "Content-Type: application/pdf" \
-T scan.pdf
# 3. Start processing
curl -s -X POST https://api.fastocr.org/v1/documents/<id>/start \
-H "Authorization: Bearer $FASTOCR_KEY"
# 4. Poll until ready (status: completed, partial, or failed)
curl -s https://api.fastocr.org/v1/documents/<id> \
-H "Authorization: Bearer $FASTOCR_KEY"
# 5. Download the result
curl -s https://api.fastocr.org/v1/documents/<id>/output?format=text \
-H "Authorization: Bearer $FASTOCR_KEY"Accepted files: PDF only, up to 1 GB.
Output formats: ?format=text for plain text, ?format=pdf for a searchable PDF.
Statuses: awaiting_upload → processing → completed or failed. Large documents may finish as partial with is_truncated: true.
POST/v1/documents
Create a new document job and get a presigned upload URL.
Required headers
Idempotency-Key — a unique value per job. See Idempotency.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| filename | string | Yes | Must end with .pdf. |
| size_bytes | integer | Yes | File size. Max 1,073,741,824 (1 GB). |
| sha256 | string | No | Hex-encoded SHA-256 checksum. |
| external_id | string | No | Your own correlation ID. |
Response 201
{
"id": "doc_a1b2c3d4e5f6",
"status": "awaiting_upload",
"upload_url": "https://s3.amazonaws.com/...",
"expires_at": "2025-01-15T13:00:00Z"
}GET/v1/documents
List your documents with optional filtering. See Pagination for query parameters.
Response 200
{
"documents": [
{
"id": "doc_a1b2c3d4e5f6",
"status": "completed",
"external_id": null,
"pages_billed": 5,
"pages_total": 10,
"pages_processed": 10,
"is_truncated": false,
"outputs": {
"text": { "available": true },
"pdf": { "available": true }
}
}
],
"next_cursor": null
}GET/v1/documents/{id}
Get the current status and metadata for a single document.
Response 200
{
"id": "doc_a1b2c3d4e5f6",
"status": "completed",
"external_id": null,
"pages_billed": 5,
"pages_total": 10,
"pages_processed": 10,
"is_truncated": false,
"outputs": {
"text": { "available": true },
"pdf": { "available": true }
}
}Response fields
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Document job ID. |
| status | string | Yes | awaiting_upload, processing, completed, partial, or failed. |
| external_id | string? | No | Your correlation ID, if set on create. |
| pages_billed | integer | No | Pages charged against your quota. |
| pages_total | integer | No | Total pages in the document. |
| pages_processed | integer | No | Pages processed so far. |
| is_truncated | boolean | No | True if processing stopped before all pages. |
| outputs | object | No | Available output formats (text, pdf). |
| error | object | No | Present when status is failed. See Errors. |
POST/v1/documents/{id}/start
Start OCR processing after the file has been uploaded. No request body required.
Response 202
{
"status": "processing"
}409 document_not_startable— the job is not in a startable state.400 upload_not_found— the file has not been uploaded yet.400 size_mismatch— uploaded file size does not matchsize_bytes.429 concurrency_limit— too many jobs in flight. Retry after theRetry-Afterheader (30s).
GET/v1/documents/{id}/output
Get a presigned download URL for the processed result.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
| format | string | Yes | text or pdf. |
Response 200
{
"format": "text",
"url": "https://s3.amazonaws.com/...",
"expires_at": "2025-01-15T13:00:00Z",
"pages_billed": 5,
"pages_total": 10
}The presigned URL expires in 1 hour. If the job is not yet complete, a 409 document_not_ready error is returned.
DELETE/v1/documents/{id}
Delete a document and its files. Deletion is asynchronous — the job transitions to deleting and is cleaned up in the background.
Response 202
{
"status": "deleting"
}Returns 409 document_processing if the document is currently being processed.