PDF to Markdown
Pricing
from $1.70 / 1,000 pages
PDF to Markdown
Turn PDF links and uploads into clean Markdown or plain text for AI use, with headings, lists and simple tables, per document or per page. No browser or paid API. Scanned pages are flagged, with no OCR.
Pricing
from $1.70 / 1,000 pages
Rating
0.0
(0)
Developer
Ishaan Pare
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Turn PDF files into clean Markdown or plain text, ready for AI tools, search and analysis, at $2 per 1,000 pages. Give it links or upload files, and get back headings, paragraphs, lists and simple tables in reading order. You don't need a browser, a login or an API key.
What you get
- One row per document, or one row per page if you need to cite page numbers
- GitHub-style Markdown, or plain text with table cells separated by tabs
- Headings worked out from font size, plus lists, paragraphs and simple tables worked out from text position
- Multi-column pages read one column at a time
- Title, author, page count, word count and table count
- A clear flag or free status row when a page has no text to read, such as a scan
Sample output
{"recordType": "document","sourceUrl": "https://example.com/annual-report.pdf","fileName": "annual-report.pdf","title": "Annual Report","author": "Jane Writer","pageCount": 1,"pagesReturned": 1,"pageNumber": null,"part": 1,"partCount": 1,"markdown": "# Annual Report\n\n## Overview\n\nThis paragraph has plenty of ordinary words in it...\n\n## Results\n\n| Region | Sales | Growth |\n| --- | --- | --- |\n| North | 1,200 | 5% |\n| South | 950 | 3% |","text": null,"wordCount": 107,"tableCount": 1,"hasTextLayer": true,"noTextLayerPages": [],"possiblyGarbled": false,"status": null,"reason": null,"fetchedAt": "2026-11-02T12:48:47.489Z"}
This comes from a small test PDF, with the Markdown shortened here. With the output format set to text, the text field is filled and the markdown field is empty.
How to use it
- Add links to PDF files, one per line, or upload files.
- Choose Markdown or plain text, and one row per document or per page.
- If you only need part of each file, set a page range, such as 1-5 or 1,3,7-9. Then press Start.
Maximum pages per file defaults to 100, so a longer file needs a higher setting. A status row tells you when a file was cut short. Maximum file size defaults to 50 MB. If you are reading very large files, raise the run's memory too.
Pricing
You pay only for pages returned, and Apify platform usage is included.
| Event | Price |
|---|---|
| Each page returned | $0.002 ($2 per 1,000) |
| Each run started | $0.00005 |
Status rows are free. So are pages with no text layer, pages that could not be read, and files that could not be opened. A 100-page PDF costs about $0.20. If a document is too long for one row and is split, you still pay by the page, not by the row.
If you set a maximum cost for the run, you get only the pages it pays for, and a status row tells you it stopped. A document cut off this way has pagesReturned set to the pages you received.
On the free Apify plan, each run returns up to 100 pages, and a status row tells you when you reach that limit. Any paid Apify plan removes it.
Status rows
The Actor always tells you what happened. Problems never stop the rest of the run. Each one gives a free row with recordType set to status, and reason says what went wrong in plain words.
| Status | Meaning |
|---|---|
| no_input | No links or files were given |
| invalid_input | The page range could not be understood |
| invalid_url | Not a valid http or https link |
| blocked_url | The link points to a private or reserved address, so it was refused |
| not_found | The server has no file at this link |
| access_denied | The server refused access |
| http_error | The server returned another error |
| download_failed | The download could not be completed |
| too_many_redirects | The link redirected too many times |
| too_large | The file is over your maximum file size |
| not_pdf | The link returned something that isn't a PDF |
| encrypted | The PDF needs a password |
| corrupt | The file is damaged and could not be read |
| too_complex | Reading the file took too long or used too much memory |
| no_text_layer | Some or all pages have no text, and noTextLayerPages lists them |
| page_failed | Some pages could not be read, and reason lists them |
| no_pages_selected | The page range matches no pages in this file |
| max_pages | The file has more pages than your maximum pages per file |
| spending_limit | The run reached your maximum cost |
| free_limit | The run reached the free plan limit |
If you only want content, filter out rows with recordType set to status.
What it can't do
- No OCR. Scanned pages have no text to read, so they are flagged and not charged. A scan with a small stamp of real text counts as text, and you get only the stamp.
- Complex tables may be imperfect. Tables are found by how text lines up, not by their borders. Merged cells, cells with long running text and tables with no clear gaps between columns can come out wrong, or as ordinary text. Small labels in a chart can look like a small table.
- Multi-column pages are worked out from positions, so unusual layouts can read in the wrong order.
- Headings come from font size only, so a bold heading in the same size as the body text stays a paragraph.
- Images and charts are not described, and rotated text goes at the end of the page.
- Page headers, footers and page numbers stay in the text.
- A paragraph that runs over a page break stays as two paragraphs.
- Some PDFs have fonts with no usable letter mapping. When that shows up as symbols, possiblyGarbled is true, but gibberish made of ordinary letters can't be detected.
- Password-protected files can't be read, and there is no input for a password. A file that opens with no password but restricts copying is read as normal, so make sure you have the right to use its content.
Long documents
Apify limits each dataset row to 9 MB. A longer document or page is split across rows, at page breaks first, then at paragraph breaks. The part and partCount fields show the order, and the other fields repeat on each part. The word and table counts describe the whole document or page, so count them once per document.
Using it with AI agents
The main inputs are lists, every field is optional, and no credentials are needed. An agent can send many links in one call and read status rows to see what went wrong.
Data and use
This Actor reads only the files you point it to. It refuses private and internal network addresses, including after a redirect, and it keeps no copy beyond this run's own storage. You are responsible for having the right to process each file. Text is extracted with the open-source PDF.js library. This Actor is not affiliated with or endorsed by Adobe, Mozilla or the publisher of any PDF.
Support
Open an issue on the Issues tab with your input and what you expected.