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, ashttps://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.