PDF to Markdown — PDF Parser & Text Extractor With OCR avatar

PDF to Markdown — PDF Parser & Text Extractor With OCR

Pricing

from $0.40 / 1,000 pdf page converteds

Go to Apify Store
PDF to Markdown — PDF Parser & Text Extractor With OCR

PDF to Markdown — PDF Parser & Text Extractor With OCR

PDF to Markdown, PDF to text: PDF text extractor/parser with PDF OCR in 16 languages, uploads/base64 and page-cited RAG chunks. $0.0005 per text page; $0.003 per OCR page instead; start extra; usage included; failed results uncharged.

Pricing

from $0.40 / 1,000 pdf page converteds

Rating

0.0

(0)

Developer

Logan Parker

Logan Parker

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Features

Limited permissions

Share

PDF to Markdown and PDF to text converter/parser reads URLs, public uploads or base64, with separate plain text, OCR in 16 languages and optional page-cited chunks for RAG. AI agents can call and pay through Apify MCP. List event rates are $0.0005 per text-layer page; $0.003 per OCR page instead of a text-layer page; start is extra, usage is included and failed results are uncharged; a 10-page text PDF costs half a cent before start.

Example result

For the public input below, this Actor returned this record in its 2026-10-28 image verification:

{
"url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
"sourceType": "url",
"inputIndex": 0,
"sourceId": "sha256:3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4",
"ok": true,
"pageCount": 1,
"pagesConverted": 1,
"pagesOcr": 0,
"title": null,
"createdAt": "2007-02-23T17:56:37+02:00",
"markdown": "Dummy PDF file",
"pages": [
{
"number": 1,
"markdown": "Dummy PDF file",
"ocr": false,
"text": "Dummy PDF file"
}
],
"text": "Dummy PDF file",
"charCount": 14,
"wordCount": 3,
"chunks": [
{
"index": 0,
"sourceId": "sha256:3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4",
"inputIndex": 0,
"pageNumber": 1,
"startOffset": 0,
"endOffset": 14,
"text": "Dummy PDF file",
"sourceUrl": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
"citationUrl": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf#page=1"
}
],
"warnings": []
}

How to use it

Start a run in Apify Console, by API or from an agent with an input like this one — it is the input Apify runs every day to test this Actor:

{"urls": ["https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"], "includeText": true, "includeChunks": true}

Start with the minimal JSON example above, then adjust the fields in the table below. Read the Example result and Output fields sections for the returned record, Errors for failure codes, and Events and prices for result events and the separate platform start.

FieldTypeRequiredDefaultMeaning
urlsarray of stringsno—HTTP/HTTPS PDF URLs; 100 MiB/file. Provide at least one source across the three input forms, at most 50 combined.
ocrenum auto · always · nevernoautoauto OCRs only pages with no usable text layer.
ocrLanguagesarray of stringsno["eng"]OCR language codes (ISO 639-2, e.g. eng, deu, fra); at most 3. Supported: eng, deu, fra, spa, ita, por, nld, pol, ces, swe, dan, nor, fin, tur, rus, ukr.
pagesstringnoallPage ranges, e.g. 1-5,8,10-12, applied to every document.
maxPagesPerDocumentintegerno300Pages beyond this are not converted (1–2,000).
includePagesbooleannotrueInclude per-page Markdown and optional page text; false omits the page array.
pdfFilestringno—One public HTTPS uploaded-file URL; at most 5 MiB. Authenticated/private uploads are unsupported.
base64Pdfsarray of stringsno[]Plain base64 or PDF data URIs; at most 5 MiB decoded/file and 10 MiB decoded/base64 batch.
includeTextbooleannofalseAdd native/OCR plain text, character count and whitespace word count.
includeChunksbooleannofalseAdd bounded page-cited plain-text RAG chunks and byte-hash identity; no model or embedding call.
chunkSizeintegerno1000Maximum Unicode code points per chunk, 100–10,000; paragraph boundaries preferred.
chunkOverlapintegerno100Code-point overlap, 0–2,000 and less than chunkSize. With size 100, set overlap 0.

Every source, including legacy URLs, must additionally fit 256 KiB (262,144 decoded PDF bytes) per selected text page, or 1,536 KiB per selected OCR page with ocr: always, with auto/never conservatively using the text allowance before conversion, after page ranges and maxPagesPerDocument are applied and before conversion. The bound is rechecked against the pages actually converted and charged, including after a spend-limit stop. Mixed results add 256 KiB per text page and 1,536 KiB per OCR page; this reflects unchanged event prices, with no change to physical page counts. For example, a 5 MiB upload needs at least 20 selected and converted pages; selecting only one page does not qualify. Outside this envelope the entire file returns too_large without a page charge.

The schema describes the fields; code also enforces combined counts, decoded sizes, overlap and output limits. Sources run in this order: URLs, uploaded file, base64. A base64 batch over 10 MiB is refused in full before decoding/conversion; URL/upload inputs can still succeed. Inputs that exceed a file bound return too_large with no page charge. The platform's automatic start remains payable, including on failures.

To request plain text and cited chunks, add "includeText": true, "includeChunks": true, "chunkSize": 1000 and "chunkOverlap": 100 to that input. For a local file, use the Console file-upload editor or supply its bytes as a base64 string in base64Pdfs; a PDF data URI must start with data:application/pdf;base64,. Base64 expands the input by roughly one third; Apify's own input/request-size limit may reject a large payload before the Actor runs. Only submit documents you may process, without personal data.

Events and prices

Pay per event; platform usage is included in the price, never passed through.

EventTitleCharged whenFREE / BRONZESILVERGOLD / PLATINUM / DIAMOND
pdf-page-convertedPDF page convertedOne page converted from its text layer to Markdown.$0.0005$0.00045$0.0004
pdf-page-ocrPDF page converted with OCROne scanned page converted by OCR; charged instead of, not in addition to, pdf-page-converted.$0.003$0.0027$0.0024

Apify also charges its standard apify-actor-start event: $0.00005 per GB of run memory (4 events, $0.0002, at the default 4,096 MB). The minimum maximum-charge a caller can set is $0.01.

Worked example at FREE: ten text pages cost 10 × pdf-page-converted + 4 × apify-actor-start; ten scanned pages cost 10 × pdf-page-ocr + 4 × apify-actor-start, with no text-conversion event in the second sum. Apply the FREE prices listed above; other tiers use their own column. Failed documents incur no page charge; the automatic start remains payable.

Short PDFs, scans and per-file pricing

At the observed 2026-10-28 prices and default memory, a long text-only PDF costs more here than on memo23/pdf-text-extractor, which charges per document plus a start fee. For one file per run, this Actor is cheaper through nineteen text pages at list price, not for every text PDF. Short text PDFs and scans favor Hermes in that dated comparison.

The comparison includes each default-memory start, direct public downloads, no proxy fee and no tax. Volume, memory, tiers or later competitor prices change the comparison. This Actor never adds a chunk, upload or plain-text fee. The exact dated comparison arithmetic is retained in the build evidence; the checked event table and start total above determine this listing's prices.

Call it from an agent

Through Apify's MCP server (https://mcp.apify.com), tool call-actor:

{"actor": "hermeskd/pdf-to-markdown", "input": {"urls": ["https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"], "includeText": true, "includeChunks": true}, "callOptions": {"maxTotalChargeUsd": 0.05, "timeout": 3600}, "waitSecs": 30}

The call returns the run's status and its defaultDatasetId. Read the records with get-dataset-items:

{"datasetId": "<defaultDatasetId from the call>", "limit": 50}

As a dedicated tool, add https://mcp.apify.com?tools=hermeskd/pdf-to-markdown to your MCP client. Single short documents finish well inside the 30-second wait, so one call-actor plus one get-dataset-items is the whole exchange. maxTotalChargeUsd caps what the run can charge; when it is reached the remaining URLs come back as charge_limit_reached records and are not charged.

Output fields

One record per input source. Old URL-only calls keep their original default fields.

FieldMeaning
urlThe submitted URL, including public upload URLs; null for base64 or invalid input.
oktrue when the document converted; false with error.
pageCountPages in the document.
pagesConvertedPages converted from the text layer (charged as pdf-page-converted).
pagesOcrPages converted by OCR (charged as pdf-page-ocr).
titleDocument title from metadata, when present. Author and other person fields are never returned.
createdAtCreation date from metadata, ISO 8601, when present.
markdownThe whole document, pages separated by a blank line, --- and a blank line.
pagesArray of {number, markdown, ocr} when includePages. With includeText or includeChunks it also contains page-local text.
warningspage_limit when pages over maxPagesPerDocument were skipped; charge_limit when the run's maximum charge stopped the document early. The record stays ok: true and only converted pages are charged.
error{code, message} when ok is false.
sourceTypeurl, upload or base64; present for new input forms and when chunks are requested.
sourceIdsha256: plus the hash of original PDF bytes, when identity is computed.
inputIndexZero-based combined source position; distinguishes repeated identical files.
textOptional normalized native/OCR plain text, selected pages joined by two newlines; no Markdown syntax is introduced.
charCountUnicode code points in text, including page separators; not a token count.
wordCountWhitespace-delimited word count in text.
chunksOptional page-local plain-text chunks with exact offsets, byte identity and physical page citations.

Document lifetime

The Actor deletes its default stored run INPUT immediately after reading it, before validation or conversion, including refusals and errors. Base64 content and downloaded PDFs are processed in memory; no raw PDF is deliberately written to Actor storage. If deleting INPUT fails, conversion does not start. Converted output and provenance remain in the dataset. Public upload URLs point to caller/platform-owned storage: this Actor cannot delete that external original; the uploader controls its lifetime and access. Platform request logs, backups and pre-run input handling are outside this local SDK proof.

Page-cited RAG chunks

Each chunk contains index, sourceId, inputIndex, pageNumber, startOffset, endOffset and text. Offsets are zero-based Unicode code points in the normalized page text (start inclusive, end exclusive), not PDF byte offsets or offsets into Markdown. Physical page numbers count covers/front matter and do not infer printed page labels. Chunks never cross pages and never invent a semantic heading; headings and lists remain in Markdown, while chunks use native plain text. Empty or whitespace-only pages have no chunks.

URL/upload chunks additionally retain the exact submitted sourceUrl and a citationUrl with #page=N; PDF viewers may ignore that fragment. A base64 chunk has its byte hash and physical page, but no public URL is invented. Keep identity and page fields when indexing. When a URL's bytes change, its source hash changes; update the document in the index. To verify chunk offsets, request includePages and read each page's text. With includePages false the chunk still carries its exact page-local offsets.

The caller controls maximum chunk size and overlap; paragraph boundaries may make a chunk shorter. At most 1,024 chunks per converted page (and 10,000 per PDF), and 64 KiB (65,536 bytes) of complete serialized UTF-8 JSON per charged page (and 6 MiB per result) are accepted. All fields, duplicated page text, JSON escaping, chunk citations and overlap count toward the JSON bound; size remains 100–10,000 code points and overlap 0–2,000, strictly less than size. Large overlap may exceed the output bound even for a tiny PDF. An oversized requested representation returns too_large before storage/page charging; text, chunks and provenance are never silently cut to fit. Reduce pages or optional output fields and retry. Spend/page limits can still stop conversion early, explicitly indicated by the existing warnings.

Limits and run time

  • 1–50 combined inputs. Legacy URLs: 100 MiB/file. Uploaded public HTTPS URLs and base64: 5 MiB/file. Base64 batch: 10 MiB decoded. Up to 2,000 pages per document (300 by default); Also 256 KiB PDF bytes per selected/converted text page or 1,536 KiB per OCR page (auto uses text allowance before conversion); JSON at most 64 KiB and 1,024 chunks per charged page, with absolute caps of 6 MiB and 10,000 chunks/PDF.
  • Each request — its redirects and its whole body included — must finish within 30 seconds (the per-request timeout; a slower file is download_failed); at most 2 requests a second go to one host.
  • Run memory is fixed at 4,096 MB, which Apify runs on one full CPU core; documents are converted one at a time. Historical URL-only measurements, before the page-relative byte envelope, covered 300 pages, a 95 MB scan and fifty URLs at under 400 MiB peak; those measurements do not waive the current acceptance bounds.
  • Typical run time at the default memory: a one-page text PDF in a few seconds; the prior half-core timing estimates are historical and do not describe this allocation. Cold one-page and admitted-boundary measurements are retained with the build evidence. The default run timeout is 3,600 seconds.
  • OCR runs on one core at a time. The one-core allocation avoids import throttling without paying for unused extra cores; source byte/output bounds and all per-event prices are unchanged. The automatic start units and total are listed in Events and prices. A document that runs out of time returns timeout and nothing is charged for it.

Errors

Errors are records with ok: false and error.code; none is charged.

error.codeMeaning
download_failedThe URL did not return the file (status or network error).
not_pdfThe response is not a PDF, or the file is damaged and cannot be read as one.
too_largeSource exceeds its file/batch bound or 256 KiB per selected/converted text page or 1,536 KiB per OCR page; output exceeds 64 KiB JSON / 1,024 chunks per charged page or 6 MiB / 10,000 chunks per PDF. No page charge.
encryptedPassword-protected.
robots_disallowedrobots.txt forbids fetching the URL.
blocked_hostThe host is on the deny-list, or resolves to a private or local address.
timeoutThe document did not finish within the run's time budget.
internal_errorUnexpected failure; message carries the class.
charge_limit_reachedThe run reached its maximum total charge before this URL; it was not processed.
invalid_inputThe run input passed the input schema but cannot be used (for example a descending page range such as 5-3, or no source at all); the message names the field. One record per input given, or one with url: null when none was given; nothing is processed.

The run fails only when every input failed with an Actor-side code (internal_error, timeout), so a broken Actor is visible. Every other run succeeds — including one where nothing converted because of the caller's own inputs (bad URL, robots, deny-list, not found, invalid input, the charge limit), or where those and Actor-side failures are mixed.

Sources and terms

The source is the caller's PDF, supplied as a URL, public uploaded-file URL or bounded base64 bytes. Process only documents you have the right to process. Fetching follows the Hermes fetch policy: robots.txt is obeyed for the user-agent HermesBot (and *), and a disallowed URL is refused without a request; platforms whose terms forbid automated access, and people-search sites, are on a deny-list and refused without a request; private and local addresses are refused, after DNS and on every redirect; the user-agent is HermesBot/1.0 (+https://apify.com/hermeskd); no login, cookies, credentials, CAPTCHA solving, evasion or proxies are used. Uploaded URLs follow that same policy; no private key-value store lookup, token, login or permission expansion is used. Base64 bytes are processed locally and never sent to an external model. Document metadata is limited to the title and creation date; author fields are dropped. Do not submit personal data.

Not affiliated

This Actor is not affiliated with Adobe, memo23 or with any publisher of the documents it converts. Tesseract, pdfminer.six, pypdfium2 and pypdf are used under their open-source licences.

Changelog

  • 1.1 (2026-10-28) — bounded base64 and public file-upload input; optional native plain text and page-cited RAG chunks with configurable character size/overlap; bounded JSON output checked before page charge. Title, prices, events, OCR languages and fetch policy unchanged. The listing explains the short/scanned and long text-only price tradeoff.

  • 1.0 (2026-10-27) — store title, description, search-engine title and description and the README's opening sentence carry the searched phrases "PDF to Markdown", "PDF to text", "PDF text extractor", "PDF OCR" and "PDF parser"; prices and behaviour unchanged.

  • 1.0 (2026-10-26) — store listing rewritten for the people and agents searching for this job: title, description, search-engine title and description, categories, and the README in the order a searcher reads it (what it does, a real result, how to use it, prices, the agent call).

  • 1.0 (2026-10-16) — input the Actor cannot use is answered with invalid_input records and the run succeeds; a run fails only when every input failed on the Actor's side.

  • 1.0 (2026-10-14) — first release: text layer and OCR per page, page ranges, page cap, per-page output.