The fastest way to convert a PDF to Markdown programmatically is a single HTTP request: POST the file to https://api.marklipi.com/convert and you get JSON back with the Markdown inside. No API key, no signup, no library to install — the free tier allows 10 conversions a minute and 100 a day per IP.
This works for text-layer PDFs: bank statements, contracts, invoices, reports, papers — anything where you can select the text in a PDF viewer. Scanned or image-only PDFs need OCR instead (here’s how to tell the difference).
Convert a PDF to Markdown with curl
curl -s https://api.marklipi.com/convert -F "file=@statement.pdf"
Response:
{
"markdown": "# Account Statement\n\n| Date | Description | Amount |\n...",
"filename": "statement.pdf",
"characters": 18342
}
That’s the whole integration. Save just the Markdown with jq:
curl -s https://api.marklipi.com/convert -F "file=@statement.pdf" | jq -r .markdown > statement.md
Convert a PDF to Markdown in Python
No SDK needed — the standard requests library does it:
import requests
with open("statement.pdf", "rb") as f:
resp = requests.post(
"https://api.marklipi.com/convert",
files={"file": ("statement.pdf", f, "application/pdf")},
timeout=60,
)
resp.raise_for_status()
markdown = resp.json()["markdown"]
with open("statement.md", "w") as out:
out.write(markdown)
Feeding the result to an LLM afterwards? Markdown typically costs 60–90% fewer tokens than pushing the raw PDF at a vision model — the token math is here.
Convert a PDF to Markdown in Node.js
Modern Node (18+) has fetch and FormData built in:
import { readFile } from "node:fs/promises";
const bytes = await readFile("statement.pdf");
const form = new FormData();
form.append("file", new Blob([bytes], { type: "application/pdf" }), "statement.pdf");
const resp = await fetch("https://api.marklipi.com/convert", {
method: "POST",
body: form,
});
if (!resp.ok) throw new Error(`convert failed: ${resp.status}`);
const { markdown } = await resp.json();
console.log(markdown);
Handling errors
The API returns errors as JSON with a detail field:
| Status | Meaning | What to do |
|---|---|---|
413 | File over 25 MB | Split the PDF or compress it |
422 | No text layer (scanned/image PDF) | Route to an OCR pipeline instead |
429 | Rate limit hit (10/min or 100/day per IP) | Back off and retry, or get a key with higher limits |
The 422 behavior is deliberate: marklipi extracts the existing text layer and never runs OCR, so a scan returns a clear error instead of hallucinated text.
Why not just use a Python PDF library?
Libraries like pdfplumber, PyMuPDF, or Marker work well if you want local processing and are happy managing the dependency (and for Marker, a GPU). The trade-off is setup and maintenance versus one stateless HTTP call. Files sent to marklipi are processed in memory and discarded — nothing is stored. For a comparison of the options, see the best PDF-to-Markdown tools compared.
FAQ
Do I need an API key?
No. Basic use is keyless — the free tier is 10 conversions/minute and 100/day per IP.
What’s the maximum file size?
25 MB per PDF.
Does it keep tables?
Yes — tables in the text layer come out as Markdown tables, which is most of the point for statements and financial documents.
Can I run this from a browser instead?
Yes — the free in-browser converter uses the same API with a drag-and-drop UI.