PDF to Markdown — PDF Parser & Text Extractor With OCR
Pricing
from $0.40 / 1,000 pdf page converteds
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
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Features
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.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
urls | array of strings | no | — | HTTP/HTTPS PDF URLs; 100 MiB/file. Provide at least one source across the three input forms, at most 50 combined. |
ocr | enum auto · always · never | no | auto | auto OCRs only pages with no usable text layer. |
ocrLanguages | array of strings | no | ["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. |
pages | string | no | all | Page ranges, e.g. 1-5,8,10-12, applied to every document. |
maxPagesPerDocument | integer | no | 300 | Pages beyond this are not converted (1–2,000). |
includePages | boolean | no | true | Include per-page Markdown and optional page text; false omits the page array. |
pdfFile | string | no | — | One public HTTPS uploaded-file URL; at most 5 MiB. Authenticated/private uploads are unsupported. |
base64Pdfs | array of strings | no | [] | Plain base64 or PDF data URIs; at most 5 MiB decoded/file and 10 MiB decoded/base64 batch. |
includeText | boolean | no | false | Add native/OCR plain text, character count and whitespace word count. |
includeChunks | boolean | no | false | Add bounded page-cited plain-text RAG chunks and byte-hash identity; no model or embedding call. |
chunkSize | integer | no | 1000 | Maximum Unicode code points per chunk, 100–10,000; paragraph boundaries preferred. |
chunkOverlap | integer | no | 100 | Code-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.
| Event | Title | Charged when | FREE / BRONZE | SILVER | GOLD / PLATINUM / DIAMOND |
|---|---|---|---|---|---|
pdf-page-converted | PDF page converted | One page converted from its text layer to Markdown. | $0.0005 | $0.00045 | $0.0004 |
pdf-page-ocr | PDF page converted with OCR | One 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.
| Field | Meaning |
|---|---|
url | The submitted URL, including public upload URLs; null for base64 or invalid input. |
ok | true when the document converted; false with error. |
pageCount | Pages in the document. |
pagesConverted | Pages converted from the text layer (charged as pdf-page-converted). |
pagesOcr | Pages converted by OCR (charged as pdf-page-ocr). |
title | Document title from metadata, when present. Author and other person fields are never returned. |
createdAt | Creation date from metadata, ISO 8601, when present. |
markdown | The whole document, pages separated by a blank line, --- and a blank line. |
pages | Array of {number, markdown, ocr} when includePages. With includeText or includeChunks it also contains page-local text. |
warnings | page_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. |
sourceType | url, upload or base64; present for new input forms and when chunks are requested. |
sourceId | sha256: plus the hash of original PDF bytes, when identity is computed. |
inputIndex | Zero-based combined source position; distinguishes repeated identical files. |
text | Optional normalized native/OCR plain text, selected pages joined by two newlines; no Markdown syntax is introduced. |
charCount | Unicode code points in text, including page separators; not a token count. |
wordCount | Whitespace-delimited word count in text. |
chunks | Optional 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
timeoutand nothing is charged for it.
Errors
Errors are records with ok: false and error.code; none is charged.
error.code | Meaning |
|---|---|
download_failed | The URL did not return the file (status or network error). |
not_pdf | The response is not a PDF, or the file is damaged and cannot be read as one. |
too_large | Source 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. |
encrypted | Password-protected. |
robots_disallowed | robots.txt forbids fetching the URL. |
blocked_host | The host is on the deny-list, or resolves to a private or local address. |
timeout | The document did not finish within the run's time budget. |
internal_error | Unexpected failure; message carries the class. |
charge_limit_reached | The run reached its maximum total charge before this URL; it was not processed. |
invalid_input | The 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.
Related Hermes Actors
- AI Crawler Checker: Which AI Bots robots.txt Allows per URL — check declared robots.txt permissions for six AI crawlers at URL paths.
- Article Extractor — News & Blog Text, Date and Markdown by URL — an article's clean text, title and publish date, without the rest of the page.
- ATS Job Search — Jobs Confirmed Open on Company Career Boards — search open jobs in the Hermes directory of Greenhouse and Lever boards, each confirmed live.
- Speech to Text — Transcribe Audio & Video URLs, Speaker Labels — speech to text with SRT and VTT subtitles.
- Video Converter — MP4 to MP3, Trim, GIF and Audio Extraction — audio and video conversion: MP4 to MP3, trim, GIF.
- Broken Links Checker — Links, Assets, Redirects and Their Pages — broken links, 404s and redirects on a site.
- ATS Detector — Company Hiring System & Job Board Lookup — which hiring system and job board a company uses.
- SEC EDGAR Filings — Recent Company Forms, Dates and XBRL Flags — Read recent company financial filing metadata from the official SEC JSON API
- DOI Lookup — Crossref Titles, Venues, Dates and Citation Counts — crossref doi metadata.
- CVE Vulnerability Lookup — NVD CVSS Scores and Exploited Flags — look up NVD CVE dates, status, numeric CVSS scores and severity.
- Merge JSON Datasets — Deduplicate Rows, Export JSON and CSV — json dataset cleaner.
- DNS Lookup — Records, SPF Lookup Counts, DKIM & DMARC by Domain — DNS records and SPF, DKIM and DMARC checks.
- DOCX to Markdown — Word, Excel, PowerPoint and EPUB Converter — Word, Excel, PowerPoint and other office files to Markdown.
- Domain Availability Checker — Bulk RDAP Status and Registrar — whether domain names are available, from registry RDAP.
- USGS Earthquake Lookup — Event Magnitude, Depth, Coordinates — Read numeric USGS earthquake metadata for known event identifiers.
- Currency Exchange Rates — ECB Daily Euro Rates and Cross Pairs — Read latest ECB daily currency reference rates and calculated cross pairs.
- Bulk File Downloader — Save URL Lists to Storage With SHA-256 — files and images from URLs, saved with a public link each.
- GitHub Repo Stats — Stars, Forks, Subscribers and Open Issues — Read numeric metrics for known public GitHub repositories.
- Greenhouse Jobs — Live Openings, Offices and Apply Links — every open job on a company's Greenhouse board.
- Hacker News Story Metrics — Scores, Comment Counts, Timestamps — read numeric Hacker News story scores, timestamps and comment counts by ID.
- HTTP GET Request — Bulk Response Bodies, Status and SHA-256 — public http get.
- Security Headers Checker — HSTS, CSP, Framing, Nosniff by URL — Check seven declared HTTP security header families without returning raw values.
- Image Background Remover — U2NetP Cutouts for JPEG, PNG, WebP — Remove image backgrounds with the small U2NetP model and return transparent PNG pixels as base64
- Image Converter — JPEG, PNG and WebP With Resize and Quality — image format converter.
- Image Metadata Remover — EXIF and GPS Scrub, Pixels Verified — GPS location, camera serial numbers and other private metadata removed from photos, losslessly.
- Image to Text OCR — Text With Word Positions and Confidence — OCR: the text in images.
- Image Upscaler — Real-ESRGAN 2x/4x for Photos and Graphics — image upscaling 2x or 4x, and photo restoration.
- Lever Jobs Scraper — Job Board Postings With Salary, US & EU — every published job on a company's Lever site, global or EU.
- Lighthouse Audit — Lab Web Vitals and Scores, Mobile & Desktop — Lighthouse scores and Core Web Vitals.
- npm Package Lookup — Latest Version, License, Dependency Count — read latest npm package versions, license tokens and dependency counts.
- Website Change Monitor — Page Text Diffs Against Your Snapshots — what changed on a page since the last check.
- Public Holidays Calendar — Holiday Dates for Five Countries — build offline public-holiday calendars for five countries and bounded years.
- Remote Jobs Search — Remote OK Jobs by Keyword, Tag and Salary — current remote jobs from Remote OK, with salary and listing links.
- Research Paper Search — OpenAlex Papers, DOIs, Citation Counts — Search OpenAlex for work-level paper metadata without authors, affiliations, abstracts or full text
- RSS Feed Reader — Atom and JSON Feed Parser With Enclosures — every item of an RSS, Atom or JSON feed.
- SEO Audit — On-Page Score, Meta Tags, Schema & Fix Guidance — an on-page SEO audit: meta tags, schema, headings and links.
- Sitemap Extractor — Unique URLs From XML, Gzip & Index Sitemaps — the URLs in a site's sitemaps.
- Text to Speech — Offline English, German, Spanish WAV Voices — Convert short nonpersonal texts to offline formant WAV speech for agents
- Time Zone Converter API — Convert one offset-qualified instant to named IANA time zones using pinned data.
- URL to Markdown — Clean Text for LLM & RAG, With Selectors — a public job page as clean Markdown where the site allows it (deny-listed job sites are refused).
- Extract Video Frames — Timed Stills by Interval or Scene Cut — frames, thumbnails and scenes from a video.
- Website Color Palette — CSS Colors With Alpha and Usage Counts — Extract declared website CSS color literals and counts from public HTML and bounded linked stylesheets
- Favicon Extractor — Icons, Touch Icons, Manifests, Theme Color — declared website icons, theme colors and manifest links.
- Website Screenshot — Full Pages, Elements, Dark Mode & PDF — screenshots and PDF prints of web pages.
- Tech Stack Detector — Website Technologies With Match Evidence — the technologies a website runs, detected live.
- Website Crawler to Markdown — Same-Site Pages for LLM and RAG — bounded whole-site Markdown with robots and crawl-delay enforced
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_inputrecords 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.