OCRmyPDF as an API

Send a scanned PDF or image and get it back as a searchable PDF/A. OCRmyPDF and Tesseract, hosted, behind one API key.

Last updated

Price 2 credits per page. An image counts as one page.
Files PDF, PNG or JPEG, up to 25 MB and 200 pages
Languages English, German, Spanish and French
Output PDF/A-2b by default, or a regular PDF
Time limit 15 minutes per job
Results Kept for 7 days after submission

OCRmyPDF adds a text layer to scanned PDFs and images. The pages look the same, but you can search, select and copy their text. Tesseract recognizes the text.

You send one file to the queue and get a job id back. When the job has succeeded, you download the searchable PDF. The output is PDF/A-2b for long-term archiving, unless you ask for a regular PDF.

Price and limits

A job costs 2 credits per page, and an image counts as one page. The credits are charged when you submit the job. If the job fails, they are refunded.

A file can be up to 25 MB and 200 pages. A job is stopped after 15 minutes. The result is kept for 7 days after submission, then deleted. The uploaded file is deleted as soon as the job has finished. Plans and credit grants are on the pricing page.

Self-hosted or hosted

To run OCRmyPDF yourself, you install it with Tesseract and one language pack per language. You keep both up to date, and you give every job a time and memory limit. A long scan can use several GB of memory.

Hosted, you send the file with one API key. The same key and credit balance work for the other document engines on this site.

Quickstart with curl

Submit a scan. The type= part sets the file's content type:

curl -H "X-API-Key: $KEY" \
  -F "file=@scan.pdf;type=application/pdf" \
  -F language=deu -F rotate_pages=true \
  https://api.pagespool.com/v1/ocrmypdf/jobs

The response names the job and what it costs:

{"job_id": "3f2a…", "status": "queued", "pages": 3, "credits": 6, "poll_url": "/v1/jobs/3f2a…", "result_url": "/v1/ocrmypdf/jobs/3f2a…/result"}

Poll the job until status is succeeded or failed:

curl -H "X-API-Key: $KEY" https://api.pagespool.com/v1/jobs/JOB_ID

Then download the searchable PDF:

curl -H "X-API-Key: $KEY" -o scan-ocr.pdf https://api.pagespool.com/v1/ocrmypdf/jobs/JOB_ID/result

Polling and downloading are free.

Quickstart with Python

import time

import httpx

API = "https://api.pagespool.com"
headers = {"X-API-Key": "YOUR_KEY"}

with open("scan.pdf", "rb") as fh:
    resp = httpx.post(
        f"{API}/v1/ocrmypdf/jobs",
        headers=headers,
        files={"file": ("scan.pdf", fh, "application/pdf")},
        data={"language": "eng", "deskew": "true"},
        timeout=120,
    )
resp.raise_for_status()
job = resp.json()

while httpx.get(f"{API}{job['poll_url']}", headers=headers).json()["status"] not in (
    "succeeded",
    "failed",
):
    time.sleep(5)

result = httpx.get(f"{API}{job['result_url']}", headers=headers, timeout=120)
result.raise_for_status()  # a failed job answers its reason as a problem
with open("scan-ocr.pdf", "wb") as out:
    out.write(result.content)

Options

Send the options as form fields next to file:

Field Values Default
language eng, deu, spa, fra eng
output_type pdfa (PDF/A-2b), pdf pdfa
mode skip, redo, force skip
deskew true, false false
rotate_pages true, false false

mode decides what happens to pages that already have text. skip leaves them as they are. redo replaces an earlier OCR layer. force runs OCR on every page as an image. mode=redo cannot be combined with deskew. That request answers 400 and costs nothing.

Errors

Every error is a JSON problem document with a code. A refused submission costs nothing. A failed job is refunded, and its result URL answers the reason:

Code Status Meaning
incompatible_options 400 mode=redo together with deskew
payload_too_large 413 The file is larger than 25 MB
unsupported_media_type 415 The file is not a PDF, PNG or JPEG
too_many_pages 422 The file has more than 200 pages
bad_input 422 The file cannot be read, or an image has transparency
encrypted_pdf 422 The PDF needs a password to open
already_has_text 409 The pages already have text: send mode=redo or mode=force
pdfa_conversion_failed 422 The result is not a valid PDF/A: send output_type=pdf
job_not_ready 409 The job has not finished yet
result_expired 410 The result was deleted after 7 days
ocr_failed, ocr_timeout 500 The OCR failed or ran longer than 15 minutes

API keys

Every OCR call needs an API key. Without a valid key, a call answers 401. You can send the key in three ways:

  • the header X-API-Key: YOUR_KEY,
  • the header Authorization: Bearer YOUR_KEY,
  • HTTP Basic with any user name and the key as the password, such as curl -u "x:YOUR_KEY". A client that only takes a base URL can carry the key in it, as https://x:YOUR_KEY@ followed by the API host.

Never put the key into a path or a query string. Those end up in access logs.

MCP server

OCRmyPDF has its own MCP server at https://api.pagespool.com/mcp/ocrmypdf/. It offers two tools. ocr_pdf queues a file, sent as base64 up to 4 MB or as a download link up to 25 MB. get_ocr_result reports the job and, once it has succeeded, a download link to the PDF that works for 60 minutes. The tools need an API key and cost the same as the API.

Try it without code

The free OCR tool runs the same OCR on files up to 3 pages and 4 MB, with no account.

OCRmyPDF is a trademark of its owner; pagespool is not affiliated.