Convert PDF to Editable PDF Using OCR
PDF4me Convert PDF to Editable PDF using OCR is a REST endpoint that makes scanned PDFs searchable and editable. POST a Base64 PDF to /api/v2/ConvertOcrPdf, choose Draft or High quality, and the OCR engine writes a real text layer into the document. The response returns the finished PDF as Base64 JSON, ready to decode and save.
Takes an image-based or scanned PDF and returns the same document with recognized, selectable text. qualityType switches between a fast single pass (Draft, 1 API call per file) and per-page recognition (High, 2 API calls per page), while ocrWhenNeeded skips pages that are already searchable. The output arrives as a Base64 docContent field in a JSON response, or via a Location poll URL on 202.
Authenticating Your API Request
Every PDF4me REST call must include your API key in the Authorization header as Basic auth. Get or rotate your key from the developer dashboard.
Endpoint
/api/v2/ConvertOcrPdfhttps://api.pdf4me.com/api/v2/ConvertOcrPdfImportant Facts You Should Not Miss
ocrWhenNeeded and outputFormat are the STRINGS "true" / "false", while isAsync and mergeAllSheets are JSON booleans. This mirrors the official code samples; mixing them up is a common cause of 400 errors.docName plus docContent, the finished PDF as a Base64 string. Decode docContent before saving. Do not write the response body to disk as-is.ocrWhenNeeded: "true" so already-searchable pages are skipped instead of re-processed.HTTP setup
Method: POST
URL: https://api.pdf4me.com/api/v2/ConvertOcrPdf
Content-Type: application/json
Authorization: Basic <your PDF4me API key>
Send isAsync: true in the body. 200 returns JSON with the Base64 docContent. 202 returns a Location header with a poll URL; GET that URL with the same Authorization header until it returns 200 with the JSON result.
How do you make a scanned PDF searchable?
A scanned PDF is just pictures of pages; nothing is selectable and nothing matches a text search. OCR (optical character recognition, see the overview of how OCR works) reads each page image and writes the recognized words into the file as a real text layer. After conversion the document behaves like a born-digital PDF: search, copy, and screen readers all work, and it is ready for downstream steps like PDF/A archiving or find-and-replace.
| Draft vs High | Draft | High |
|---|---|---|
| Best for | Normal PDFs that mostly have a text layer | Scanned or image-based documents |
| Cost | 1 API call per file | 2 API calls per page |
| Recognition | Light pass | Full per-page OCR |
| Pair with | ocrWhenNeeded: "true" to skip searchable pages | language when text comes back garbled |
API body fields
| Parameter | Required | Type | What it does | Example |
|---|---|---|---|---|
docContent | Required | string | Base64-encoded bytes of the source PDF. Strip any data:application/pdf;base64, prefix before posting. | JVBERi0xLjcK... |
docName | Required | string | Source filename including the .pdf extension. Used for the output docName. | scanned-contract.pdf |
qualityType | Required | string | Draft for normal PDFs (1 API call per file). High for scanned documents (2 API calls per page). | High |
ocrWhenNeeded | Required | string | The string "true" skips pages that already have a searchable text layer; "false" forces OCR on every page. | "true" |
outputFormat | Required | string | Output format flag, sent as the string "true" in the official samples. | "true" |
language | Conditional | string | Language of the source text (English, Spanish, French, German, and others). Set only when the recognized output is garbled; otherwise let the engine detect it. | English |
mergeAllSheets | Optional | boolean | JSON boolean carried by the official samples; relevant to sheet-based sources. | true |
isAsync | Optional | boolean | true enables the 202 + Location polling pattern, recommended for large scans. | true |
Sample payloads
High mode. scanned document with OCR
{
"docContent": "JVBERi0xLjcKJcfsj6IKNSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZw...",
"docName": "scanned-contract.pdf",
"qualityType": "High",
"ocrWhenNeeded": "true",
"language": "English",
"outputFormat": "true",
"isAsync": true
}
Draft mode. mixed document, skip searchable pages
{
"docContent": "JVBERi0xLjcKJcfsj6IKNSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZw...",
"docName": "mixed-report.pdf",
"qualityType": "Draft",
"ocrWhenNeeded": "true",
"outputFormat": "true",
"isAsync": true
}
Postman collection tips
curl example
curl -X POST https://api.pdf4me.com/api/v2/ConvertOcrPdf \
-H "Content-Type: application/json" \
-H "Authorization: Basic YOUR_API_KEY" \
-d '{
"docContent": "'"$(base64 -w 0 scanned-contract.pdf)"'",
"docName": "scanned-contract.pdf",
"qualityType": "High",
"ocrWhenNeeded": "true",
"outputFormat": "true",
"isAsync": true
}' | python -c "import sys, json, base64; open('searchable.pdf','wb').write(base64.b64decode(json.load(sys.stdin)['docContent']))"
What does the API return?
JSON, not raw file bytes. Decode the docContent field to get the finished PDF.
| Field | Type | What it contains |
|---|---|---|
| docName (HTTP 200) | String | The output PDF filename, derived from the docName you sent. |
| docContent (HTTP 200) | String (Base64) | The searchable, editable PDF encoded as Base64. Decode to bytes and save with a .pdf extension. |
| Location header (HTTP 202) | String (URL) | Poll URL for an async job that is still running. GET it with the same Authorization header; the official samples poll every 10 seconds, up to 20 retries. |
| Poll response (HTTP 200) | JSON | The same docName + docContent JSON, returned once processing completes. |
Code samples
Working end-to-end implementations, each with a sample scanned PDF and the exact payload from this page: