marker-api

Flask API wrapper around marker — converts PDFs, DOCX, XLSX, PPTX, EPUB, images (PNG/JPG/BMP/GIF/TIFF/WEBP/HEIC), and HTML to Markdown (JSON/HTML/chunks).


Quick Start

# Build and run with Podman/Docker
podman build -t marker-api -f Containerfile .
podman run -d --rm \
  --name marker-api \
  -p 8000:8000 \
  -e AMD_COMPUTE=false \
  -e TORCH_DEVICE=cpu \
  marker-api

# Or use docker-compose
docker-compose up -d

Bare-metal

git clone https://github.com/your-org/marker-api.git /app/marker-api
pip install -e /app/marker-api/marker[full] flask gunicorn
PORT=8000 python /app/marker-api/app.py

Health Check

curl http://localhost:8000/health
# {"status":"ok","ollama":"http://localhost:11434","torch_device":"cpu","supported_formats":["docx","epub","html","jpg",...]}

Endpoints

GET /

HTML documentation page listing all endpoints and parameters.

GET /health

Returns server status, torch device, supported file formats, and configuration.

POST /marker

Convert a single file. Accepts multipart/form-data or application/json.

Multipart form-data

curl -X POST http://localhost:8000/marker \
  -F "file=@document.pdf" \
  -F "output_format=markdown" \
  -F "force_ocr=false"

When output_format=markdown, the response is the raw .md content as a file download. All other formats return JSON.

JSON body (base64)

curl -X POST http://localhost:8000/marker \
  -H "Content-Type: application/json" \
  -d '{
    "file_b64": "<base64>",
    "filename": "document.pdf",
    "output_format": "markdown",
    "force_ocr": false
  }'

POST /v1/conversions

Same as /marker but always returns JSON, wrapping the result with an id (UUID) field and filename.

POST /v1/files/convert

Same as /marker but always returns JSON with filename, format, output, images_b64, and metadata.


Parameters

Parameter Type Default Description
file / file_b64 file / string required The document to convert
output_format string markdown markdown, json, html, chunks
force_ocr bool false Force OCR on all pages (fixes garbled text)
paginate_output bool false Separate pages with horizontal rules
page_range string all Comma-separated pages/ranges: "0,5-10"
disable_image_extraction bool false Skip embedded image extraction
processors string auto Comma-separated full module paths for custom processors
config_json string none Path to JSON config file
converter_cls string auto Full module path of converter (e.g. marker.converters.table.TableConverter)
use_llm bool false Use an LLM to improve accuracy
llm_service string marker.services.ollama.OllamaService LLM service class: gemini, vertex, claude, openai, azure_openai, ollama
block_correction_prompt string none Custom prompt for LLM block correction
redo_inline_math bool false Re-process inline math with LLM
strip_existing_ocr bool false Remove existing OCR text and re-OCR
debug bool false Enable debug logging

Supported Formats

PDF, DOCX, XLSX, PPTX, EPUB, PNG, JPG, BMP, GIF, TIFF, WEBP, HEIC, HTML, HTM.


Environment Variables

Variable Default Description
OLLAMA_HOST http://localhost:11434 Ollama instance for OCR fallback / LLM
DEESEEK_OCR_MODEL deepseek-ocr OCR model name in Ollama
AMD_COMPUTE false Enable AMD ROCm GPU support
TORCH_DEVICE auto PyTorch device: rocm, cuda, cpu
MODEL_DTYPE float32 Model dtype: float32, bfloat16
PORT 8000 Listening port
HOST 0.0.0.0 Listening host

PowerShell Batch Script

A PowerShell script (marker-convert-powershell/marker-convert.ps1) is provided for batch conversion.

Usage

.\marker-convert-powershell\marker-convert.ps1 -TargetFolder .\documents

# With options
.\marker-convert-powershell\marker-convert.ps1 .\documents `
  -Force -MaxConcurrency 8 -OutputFormat json -UseLlm -LlmService marker.services.ollama.OllamaService

# Remote API
.\marker-convert-powershell\marker-convert.ps1 .\documents -ApiUrl http://10.0.0.5:8000/marker

Parameters

Parameter Type Default Description
-TargetFolder string (required) Folder to scan recursively
-ApiUrl uri http://localhost:8000/marker Marker API endpoint
-OutputFormat string markdown markdown, json, html, chunks
-Force switch off Overwrite existing .md files
-MaxConcurrency int 4 Concurrent workers (1-32)
-Timeout int 300 HTTP timeout in seconds (30-1800)
-PageRange string "" Page range e.g. "0,5-10"
-ForceOcr switch off Force OCR on all pages
-DisableImageExtraction switch off Skip image extraction
-UseLlm switch off Enable LLM enhancement
-LlmService string marker.services.ollama.OllamaService LLM service class
-Processors string "" Custom processor module paths
-ConfigJson string "" Path to JSON config file
-ConverterCls string "" Custom converter class path

The script writes a CSV report (_marker_convert_results.csv) next to each converted file.


Deployment

AMD GPU (ROCm)

Set AMD_COMPUTE=true and TORCH_DEVICE=cuda in the container environment.

Vega 20 / GFX906 Support (e.g., powermac)

For older AMD GPU architectures like Vega 20 (GFX906), AMD dropped standard ROCm PyTorch support. This project fully supports GFX906 out of the box by using a patched GFX906 PyTorch base image (mixa3607/pytorch-gfx906:v2.7.1-rocm-6.3.3).

To run the container on GFX906 GPUs with hardware acceleration:

docker run -d --name marker-api \
  --network=host \
  --device /dev/kfd --device /dev/dri \
  --group-add 984 --group-add 988 \
  -e AMD_COMPUTE=true \
  -e TORCH_DEVICE=cuda \
  -e CUDA_VISIBLE_DEVICES=1 \
  -e HSA_OVERRIDE_GFX_VERSION=9.0.6 \
  marker-api:latest \
  gunicorn --bind 0.0.0.0:8000 --workers 1 --timeout 300 --worker-class gthread --threads 4 app:app_instance

Note on first run: The very first conversion on a ROCm GPU will take 2-3 minutes as MIOpen compiles convolution kernels for your exact GPU. Subsequent runs are fully cached and take ~4-5 seconds per document. Note on memory: If other services (e.g., llama-servers) are utilizing GPU 0, restrict marker-api to GPU 1 (CUDA_VISIBLE_DEVICES=1) and use a single worker (--workers 1) to prevent HIP Out-Of-Memory errors.

CPU-only

TORCH_DEVICE=cpu AMD_COMPUTE=false podman run ... marker-api

GPU (CUDA)

Override the PyTorch index URL during build, or use the existing ROCm image with TORCH_DEVICE=cuda.


Response Codes

Code Meaning
200 Successful conversion (markdown returned as file download, others as JSON)
400 Missing file or invalid body
500 Conversion error (details in JSON body)

Error responses have the shape:

{"success": false, "error": "error message"}
S
Description
No description provided
Readme 10 MiB
Languages
Python 79.5%
PowerShell 14.6%
Shell 3.2%
Dockerfile 2.7%