- Step 4 of 11 in the series "Document AI, in order"
Datalab in Practice: Marker, Surya, Chandra and the API

By the end of this guide you'll have Marker running on your own machine, turning a PDF into markdown, and you'll know how to make the same request through Datalab's paid API.
Datalab ships three open-source projects and a hosted API, so the first job is knowing which one you're actually installing. This guide follows the path most builders need: run Marker on a PDF, look at what comes out, then do the same thing through the API.
This is part 3 of the Document AI series. Every command comes from the official READMEs and docs, read on September 26, 2026. None of them were run for this article. Where an output is shown, it's what the docs say you should get, and it's labeled that way.
Pick the right project first
The three projects overlap, but the READMEs are clear about who does what.
| Project | What it is | Use it when | Install |
|---|---|---|---|
| Marker | A conversion pipeline: text layer first, Surya VLM where needed, tables, images, metadata | You want markdown, HTML, JSON, or RAG chunks out of whole documents | pip install marker-pdf |
| Surya | A 650M-parameter OCR model with layout, reading order, and table recognition | You want raw OCR lines, layout boxes, or table cells to build your own pipeline | pip install surya-ocr |
| Chandra | A full-page document VLM, version 2 released March 2026 | Scans, handwriting, math, and forms where a text-layer pipeline struggles | pip install chandra-ocr |
In short: Marker turns whole documents into clean text. Surya is the lower-level piece that reads characters and finds layout. Chandra is a bigger AI model that reads a whole page at once, for the hard cases.
Marker uses Surya under the hood, so installing Marker gets you both. Chandra is separate. The Marker README points you to Chandra for documents that need a full-page model, like math-heavy pages and scans.
Check the license before you build on any of them. The code is Apache 2.0 in all three. The model weights, the trained files that do the actual work, use a modified OpenRAIL-M license.
- The Marker and Surya READMEs make the weights free for research, personal use, and startups under $5M in funding or revenue.
- The Chandra README sets that line at $2M, and adds that you can't use the weights to compete with Datalab's API.
Above those lines, using the weights commercially needs a license from Datalab.
Step 1: install Marker and the server it runs on
The README asks for Python 3.10 or newer and PyTorch. Then:
pip install marker-pdf
Add the full extra only if you'll also convert DOCX, PPTX, XLSX, HTML or EPUB files, not just PDFs:
pip install marker-pdf[full]
Here's the part that catches people. Marker runs its AI model through a separate local server, which it starts the first time it needs it. Which server depends on your machine:
- On an NVIDIA GPU, it's vLLM in Docker. That needs Docker and the NVIDIA Container Toolkit.
- On a regular CPU or an Apple Silicon Mac, it's llama.cpp. The README's macOS instruction is:
brew install llama.cpp
The Python install succeeds either way, so nothing warns you if this step is missing. You only find out when the first conversion that needs OCR has no server to talk to.
Step 2: convert one PDF
Put your file in a working folder. The running example is the made-up Harbor Lane invoice from part 2, saved as invoice.pdf. Then run the single-file command from the README:
marker_single invoice.pdf --output_format markdown --output_dir ./out
These are the options that matter most the first time, all from the README:
--mode fastor--mode balanced. The default depends on your machine: balanced on a GPU, fast on a CPU or Apple Silicon. Balanced uses the AI model to work out the layout, and re-reads any page whose stored text is bad. Fast only calls the model for equations, garbled blocks and scanned pages.--disable_ocrturns off the AI model completely. It only uses the text already stored in the PDF, runs on a plain CPU, and skips equations and scanned pages entirely.--force_ocrre-reads every page with OCR, even when the PDF already has text stored in it. The README suggests this when the output looks garbled.--use_llmbrings in an outside LLM to join tables that run across pages, format tables, and pull out form values. It uses a Gemini model by default and needs an API key for whatever service you set up.--page_range "0,5-10"limits which pages get converted. Page numbers start at 0.
For a whole folder of files, the batch command takes the same options:
marker ./invoices --output_dir ./out
Step 3: read what came back
This is what the docs say you'll get, not output from a real run. With markdown, the README says you get the converted text with formatted tables, links to images, and equations written in LaTeX between double dollar signs. Any images it pulls out are saved in the same folder. Every output format also comes with a metadata dictionary.
The metadata is where you check whether the conversion did what you think it did. The README describes two keys:
table_of_contentslists the headings it found, with their page and position.page_statsrecords, for each page, whichtext_extraction_methodit used and how many of each kind of block it found.
Say a page looked like a scan, but page_stats shows it used the text stored in the PDF, and the text looks wrong. Rerun with --force_ocr.
Switch to JSON when you need to know where things sit on the page:
marker_single invoice.pdf --output_format json --output_dir ./out
The README describes the JSON as a list of pages, and each page is a tree of blocks. Every block has:
- an
id, like/page/0/Table/3 - a
block_type, likeSectionHeader,Table,FormorHandwriting - an
htmlversion of its content - a four-corner
polygonmarking where it sits on the page - its
children, the blocks inside it
Child blocks also carry a section_hierarchy. One catch: the page-level html uses content-ref placeholders for its children, so you have to fill those in to rebuild the full HTML. The README points to a helper in marker/output.py for that.
That tree of blocks is what lets you check the work later. When you pull a value out of the invoice, you can trace it back to a block ID. The block ID gives you a polygon, and the polygon tells you exactly where to highlight on the page.
Step 4: go lower with Surya, or bigger with Chandra
If you only want the raw OCR, Surya has three commands. Each one writes a results.json, according to the Surya README:
surya_ocr invoice.pdf
surya_layout invoice.pdf
surya_table invoice.pdf
surya_ocrreturns the text with boxes, labels, confidence scores and reading order.surya_layoutreturns labeled regions, like Text, Table and SectionHeader, with their reading positions.surya_tablereturns rows, columns, cells and HTML for each table.
For scans and handwriting, the Chandra README gives two ways in. The recommended one starts a vLLM server in Docker and then converts:
pip install chandra-ocr
chandra_vllm
chandra invoice.pdf ./output
The other runs the model on your machine through Hugging Face, and needs torch:
pip install chandra-ocr[hf]
chandra invoice.pdf ./output --method hf
What the docs say you'll get: each file gets its own folder with a .md file, an .html file, and a _metadata.json file with page details and token counts. Extracted images go in the output folder.
Step 5: the same conversion through the Datalab API
The hosted API runs Datalab's newer models on their servers, so you don't need a GPU. The quickstart installs the SDK and reads your key from the environment:
pip install datalab-python-sdk
export DATALAB_API_KEY=your_api_key_here
Then convert:
from datalab_sdk import DatalabClient, ConvertOptions
client = DatalabClient()
options = ConvertOptions(output_format="markdown", mode="balanced")
result = client.convert("invoice.pdf", options=options)
print(result.markdown)
result.save_output("output/")
The SDK waits for the job to finish for you. If you call the API directly over HTTP, the conversion docs show two steps: send the file, then keep checking the request_check_url from the response until it's done.
curl -X POST https://www.datalab.to/api/v1/convert \
-H "X-API-Key: $DATALAB_API_KEY" \
-F "file=@invoice.pdf" \
-F "output_format=markdown" \
-F "mode=balanced"
Two things in those docs are easy to miss.
First, a job can come back with status complete and success false, plus an error. So check both.
Second, requests handled in the EU don't send the content back directly. They return a signed result_url you download it from. The docs warn that Python SDK 0.5.0 doesn't follow that URL. So if the SDK hands you an empty result, that doesn't mean the document was empty.
The API has three modes: fast, balanced and accurate. The docs recommend balanced for most work and accurate for scans, complicated tables and crowded layouts. They also note that the API defaults to fast if you call it directly, so always set the mode yourself.
Step 6: pull out fields instead of whole pages
Conversion gives you the whole invoice as text. To get specific fields, like the invoice number and total, send a JSON schema to the extract endpoint. A schema is just a list of the fields you want, their types, and a short description of each. This is the quickstart from the structured extraction docs, trimmed down to the invoice:
import json
from datalab_sdk import DatalabClient, ExtractOptions
client = DatalabClient()
schema = {
"type": "object",
"properties": {
"invoice_number": {"type": "string", "description": "Invoice ID or number"},
"total_amount": {"type": "number", "description": "Total amount due"},
"vendor_name": {"type": "string", "description": "Company or vendor name"},
},
"required": ["invoice_number", "total_amount"],
}
options = ExtractOptions(page_schema=json.dumps(schema), mode="balanced")
result = client.extract("invoice.pdf", options=options)
print(json.loads(result.extraction_schema_json))
What the docs say you'll get: extraction_schema_json holds your fields. Each field also gets a list of citations, like total_amount_citations, naming the blocks the value came from. Balanced and accurate extraction also return _meta fields with a status, the model's reasoning, and whether the value checked out.
Watch out for the two mode settings, because they control different things. extraction_mode picks how carefully fields are pulled out: turbo, fast, balanced or accurate. mode picks how carefully the page is read first.
If you leave mode out, the docs say balanced and accurate extraction read the page in accurate mode, and that's billed separately. If you'll extract from the same file more than once, convert it with save_checkpoint=true and pass the checkpoint to extract. That way the document only gets read once.
What it costs, as of September 26, 2026
Datalab's pricing page lists:
- Conversion: $4 per 1,000 pages in fast or balanced mode, $10 in accurate.
- Extraction: $6 per 1,000 pages for turbo or fast, $15 for balanced, $20 for accurate, with possible compute fees on those last two.
The billing docs say each step is billed separately and added together. They describe a free monthly allowance of $20 for work-email accounts and $10 for personal ones, and a Team plan at $400 a month that includes $400 of usage.
So a balanced extraction on a two-page invoice, with the default accurate read, costs the extraction price plus the conversion price, on both pages. The document processing cost calculator has these Datalab rates built in, and adds the cost of people reviewing results, which is usually most of the bill.
Running it yourself has no per-page fee. But you need a GPU or patience with a slow CPU, a model server to keep running, and a license to stay inside. If you're a startup under the limit and already have a GPU, running Marker yourself is a sensible way to learn the output before you pay for anything.
Where this leaves you
You know which project to install, what each output contains, and how the API lines up with the local tools. What you still have to test on your own documents is the part this article couldn't: whether fast mode is good enough on your scans, and whether the hosted models are accurate enough to be worth the per-page price.
Next in the series: Extend in practice: schemas, evals and workflows. For how Datalab compares with other vendors on a shortlist, see how to choose an enterprise document tool. The previous part covers parse, extract, classify, split.



