Convert PDF to Markdown API
Pricing
from $0.002 / actor start
Convert PDF to Markdown API
Convert a PDF from a URL or file upload into clean Markdown and save the result to the run's key-value store.
Pricing
from $0.002 / actor start
Rating
0.0
(0)
Developer
Leo Yan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Security
Limited permissionsShare
PDF to Markdown Converter
Convert a PDF from a public URL or a file upload into clean Markdown. Files up to 256 MB are
supported. The .md result is written to the run's default key-value store, together with a
machine-readable OUTPUT record.
The Actor uses a fast local PDF parser that detects text-based and scanned documents, preserves reading order, and converts headings, lists, tables, links, and text formatting to Markdown. It can be called through the Apify API or from Apify Console.
Input
| Field | Type | Default | Description |
|---|---|---|---|
url | string | sample PDF | Public HTTP(S) URL of the PDF. |
fileUpload | string | - | Uploaded PDF or Apify key-value store record URL. Takes precedence over url. |
Only PDF input is accepted. The URL does not need to end in .pdf; the downloaded content is
checked for a PDF header before conversion starts. Password-protected PDFs are rejected because
their content cannot be read without the password.
Text must be embedded in the PDF. Image-only scans are not OCR'd; they produce an OUTPUT record
with error.code = "NO_TEXT" and a suggestion to use an OCR-enabled pipeline.
Output
For an input named input.pdf, the Markdown document is stored in the run's default key-value
store under input.md with content type text/markdown; charset=utf-8.
When the run finishes, the Output tab in Apify Console lists the Markdown document and links
to the OUTPUT record. These links are defined in .actor/output_schema.json.
An OUTPUT JSON record describes the result:
{"success": true,"message": "Converted a 5.1 MB PDF (12 pages) to Markdown (2.3 MB). The result is stored as \"pptdemo1.md\" in the run's key-value store.","input": {"source": "https://example.com/pptdemo1.pdf","filename": "pptdemo1.pdf","bytes": 5321132,"mb": "5.1 MB","pages": 12},"output": {"key": "pptdemo1.md","storeId": "STORE_ID","filename": "pptdemo1.md","contentType": "text/markdown; charset=utf-8","bytes": 2411724,"mb": "2.3 MB","downloadUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/pptdemo1.md"},"pricing": {"eventName": "pdf-mb","unitPriceUsd": 0.001,"chargedEvents": 6,"estimatedCostUsd": 0.006,"charged": true,"actorStart": {"eventName": "apify-actor-start","unitPriceUsd": 0.002,"events": 1,"estimatedCostUsd": 0.002,"chargedAutomatically": true},"estimatedTotalCostUsd": 0.008},"limits": {"memoryMb": 512,"maxMemoryMb": 512,"diskMb": 1024,"maxInputBytes": 268435456,"maxInputMb": 256}}
On failure, success is false, error.code identifies the problem, and error.message
contains a user-facing explanation. The OUTPUT record is written for both successful and
failed runs.
Filename rules
input.pdf->input.mdreport.PDF->report.mdreport->report.mdreport.html->report.mdreport.docx->report.mdreport.tar.gz->report.tar.md
Filenames are sanitized before use with a cross-platform filename cleaner. Directory components
are removed, characters that are invalid in filenames are replaced, reserved device names are
defused, and trailing dots or spaces are removed. The remaining name is normalized to letters,
digits, ., _, and -, and truncated to a safe length. For example, hello world.pdf
becomes hello_world.md.
Pricing
The Actor uses pay-per-event (PPE) pricing with two charges.
Per-run fee
Apify charges the synthetic apify-actor-start event automatically at $0.002 per start
($2 per 1,000 runs). It applies to every run, including runs that later fail, and is not
charged by the Actor code.
The event is charged once for every run. Because the Actor's memory is fixed at 512 MB, each run incurs exactly one start event ($0.002).
Per-MB fee
The Actor charges the event pdf-mb once per started megabyte of the input file, at
$0.001 per event:
- 1 byte to 1 MB -> 1 event -> $0.001
- 5.1 MB -> 6 events -> $0.006
- 128 MB -> 128 events -> $0.128
- 256 MB -> 256 events -> $0.256
This event is charged only after the Markdown document has been saved to the key-value store.
Failed runs, including oversized, non-PDF, password-protected, and no-text inputs, are not
charged for pdf-mb.
Total cost
| Input | Start fee | pdf-mb | Total |
|---|---|---|---|
| 1 byte to 1 MB | $0.002 | $0.001 | $0.003 |
| 5.1 MB | $0.002 | $0.006 | $0.008 |
| 128 MB | $0.002 | $0.128 | $0.130 |
| 256 MB | $0.002 | $0.256 | $0.258 |
The pricing object in OUTPUT reports both the pdf-mb charge and the automatic start fee.
Size limits
The Actor runs with 512 MB of memory and 1 GB of disk (Apify gives each run disk space equal to twice its memory). To leave headroom for PDF processing and the output file, the input limit is half the memory:
max input size = memory / 2 = 256 MB
| Memory | Disk | Maximum input |
|---|---|---|
| 512 MB (fixed) | 1 GB | 256 MB |
The Actor checks the remote Content-Length before downloading. If the server does not report a
size, the same limit is enforced while streaming the download. An oversized file produces an
OUTPUT record with error.code = "FILE_TOO_LARGE" and no pdf-mb charge.
Files larger than 256 MB cannot be processed by this Actor; split them into smaller PDFs before uploading. The default run timeout is 10 minutes.
Calling the API
Start an asynchronous run:
curl -X POST "https://api.apify.com/v2/acts/OWNER~convert-pdf-to-markdown-api/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"url": "https://www.pdfpdf.com/samples/pptdemo1.pdf"}'
The response contains data.id, data.defaultKeyValueStoreId, and data.status. Poll the run,
then read the metadata and download the result:
curl "https://api.apify.com/v2/actor-runs/RUN_ID?token=$APIFY_TOKEN"curl "https://api.apify.com/v2/key-value-stores/STORE_ID/records/OUTPUT?token=$APIFY_TOKEN"curl -OJ "https://api.apify.com/v2/key-value-stores/STORE_ID/records/pptdemo1.md?token=$APIFY_TOKEN"
Synchronous call (waits for the run to finish):
curl -X POST "https://api.apify.com/v2/acts/OWNER~convert-pdf-to-markdown-api/run-sync?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"url":"https://example.com/input.pdf"}'
Uploading a file is also supported. Upload the PDF to a key-value store, then pass the record URL
as fileUpload:
curl -X POST "https://api.apify.com/v2/acts/OWNER~convert-pdf-to-markdown-api/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"fileUpload": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/input.pdf"}'
Error codes
| Code | Meaning |
|---|---|
INVALID_INPUT | Missing/invalid URL or unsupported scheme. |
DOWNLOAD_FAILED | The source could not be downloaded (DNS, TLS, HTTP 4xx/5xx, timeout). |
EMPTY_FILE | The source returned an empty file. |
NOT_A_PDF | The file is not a valid PDF or has no readable pages. |
PASSWORD_PROTECTED | The PDF is encrypted and needs a password. |
NO_TEXT | No extractable text was found; the PDF may be a scanned image. |
CONVERSION_FAILED | The conversion engine could not produce a Markdown document. |
CONVERSION_UNAVAILABLE | The PDF conversion runtime is not available in this deployment. |
UPLOAD_FAILED | The result could not be written to the key-value store. |
FILE_TOO_LARGE | The input exceeds the run's memory-derived limit. |
TEMP_DIR_FAILED | The run could not create a temporary directory. |