Skip to main content
API Docs

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)

quickstart.py
# 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

quickstart.sh
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

FieldTypeRequiredDescription
filenamestringYesMust end with .pdf.
size_bytesintegerYesFile size. Max 1,073,741,824 (1 GB).
sha256stringNoHex-encoded SHA-256 checksum.
external_idstringNoYour own correlation ID.

Response 201

response
{
  "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

response
{
  "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

response
{
  "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

FieldTypeRequiredDescription
idstringYesDocument job ID.
statusstringYesawaiting_upload, processing, completed, partial, or failed.
external_idstring?NoYour correlation ID, if set on create.
pages_billedintegerNoPages charged against your quota.
pages_totalintegerNoTotal pages in the document.
pages_processedintegerNoPages processed so far.
is_truncatedbooleanNoTrue if processing stopped before all pages.
outputsobjectNoAvailable output formats (text, pdf).
errorobjectNoPresent 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

response
{
  "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 match size_bytes.
  • 429 concurrency_limit — too many jobs in flight. Retry after the Retry-After header (30s).

GET/v1/documents/{id}/output

Get a presigned download URL for the processed result.

Query parameters

FieldTypeRequiredDescription
formatstringYestext or pdf.

Response 200

response
{
  "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

response
{
  "status": "deleting"
}

Returns 409 document_processing if the document is currently being processed.