This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /blog/how-to-convert-pdf-to-markdown-using-python.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. How to convert PDF to Markdown in Python

Table of contents

    How to convert PDF to Markdown in Python
    TL;DR

    Convert a PDF to Markdown in Python by sending the file to the Nutrient DWS Processor API /build endpoint with output.type set to markdown. Markdown output gives LLMs and text pipelines clean, structured text instead of the PDF format’s fixed layout. This tutorial covers the request, page selection, scanned PDFs, and when to use the Data Extraction API instead.

    Markdown is the format most large language models (LLMs) and static-site tools read best: plain text with lightweight structure for headings, lists, and tables. PDFs carry that structure visually but not semantically, so feeding a raw PDF to an LLM or a search index usually loses it. Converting a PDF to Markdown restores a clean, machine-readable version of the document.

    This tutorial converts a PDF to Markdown in Python using the Nutrient DWS Processor API. For an agentic, no-code path, the PDF-to-Markdown skill and the DWS MCP Server workflow cover the same conversion from Claude.

    PDF-to-Markdown pipeline. A born-digital PDF is posted to the /build endpoint with output.type set to markdown, returning result.md. A scanned or image-only PDF first runs an OCR action to produce a searchable PDF, which is then converted to Markdown.

    Prerequisites

    Step 1 — Get an API key

    Create a free Nutrient account(opens in a new tab) and copy the API key from the dashboard.

    Step 2 — Install requests

    Install the requests library:

    Terminal window
    python -m pip install requests

    Place the source PDF in the working directory and name it document.pdf.

    Step 3 — Convert the PDF to Markdown

    Create convert.py and add the following code. It posts the PDF to the /build endpoint, sets the output type to markdown, and streams the result to result.md:

    import sys
    import requests
    import json
    response = requests.request(
    'POST',
    'https://api.nutrient.io/build',
    headers = {
    'Authorization': 'Bearer your_api_key_here'
    },
    files = {
    'file': open('document.pdf', 'rb')
    },
    data = {
    'instructions': json.dumps({
    'parts': [
    {
    'file': 'file'
    }
    ],
    'output': {
    'type': 'markdown'
    }
    })
    },
    stream = True
    )
    if response.ok:
    with open('result.md', 'wb') as fd:
    for chunk in response.iter_content(chunk_size=8192):
    fd.write(chunk)
    else:
    print(response.text)
    sys.exit(1)

    Replace your_api_key_here with the key from Step 1.

    Step 4 — Run the script

    Run the script:

    Terminal window
    python convert.py

    The API returns the Markdown, and the script writes it to result.md in the working directory.

    For a document with a heading, a paragraph, and a cleanly structured table, result.md looks like this:

    # Quarterly report
    Revenue grew across all regions.
    | Region | Revenue |
    | ------ | ------- |
    | EMEA | $1.2M |
    | AMER | $2.4M |

    Headings and lists come through as Markdown structure rather than fixed visual layout. Table fidelity depends on the source document: Cleanly structured tables convert to Markdown table syntax, while simpler or loosely formatted ones may come back as plain text rows. For guaranteed table structure — typed cells, bounding boxes, schema-shaped JSON — use the Data Extraction API instead.

    How the request works

    The /build endpoint takes a multipart request with two fields. The file field carries the PDF, and the instructions field is a JSON object describing the job: parts lists the input (referenced by the form field name file), and output.type set to markdown selects Markdown conversion. Streaming the response writes the output without holding the whole file in memory. The API allows 100 requests per minute per API key (test keys are limited to 10 per minute). Batch large jobs and add retries with exponential backoff.

    Convert only selected pages

    To convert a page range instead of the whole document, add a pages object to the part. Page indexes are zero-based, and the end value is inclusive, so the following converts the first three pages:

    {
    "parts": [
    {
    "file": "file",
    "pages": {
    "start": 0,
    "end": 2
    }
    }
    ],
    "output": {
    "type": "markdown"
    }
    }

    Convert scanned PDFs

    PDF-to-Markdown conversion works best with born-digital PDFs that already contain selectable text. For scanned or image-only PDFs, run optical character recognition (OCR) first to produce a searchable PDF. Then convert that result to Markdown.

    The first request runs OCR with an actions step and no Markdown output — the response is a searchable PDF. The part’s "file" value must match the name of the multipart field the script uploads ('file' in the Step 3 script):

    # First request: OCR the scanned PDF into a searchable PDF.
    ocr_response = requests.request(
    'POST',
    'https://api.nutrient.io/build',
    headers = {
    'Authorization': 'Bearer your_api_key_here'
    },
    files = {
    'file': open('scanned.pdf', 'rb')
    },
    data = {
    'instructions': json.dumps({
    'parts': [
    {
    'file': 'file'
    }
    ],
    'actions': [
    {
    'type': 'ocr',
    'language': 'english'
    }
    ]
    })
    }
    )
    if ocr_response.ok:
    with open('searchable.pdf', 'wb') as fd:
    fd.write(ocr_response.content)
    else:
    print(ocr_response.text)
    sys.exit(1)

    Then run the Step 3 script against searchable.pdf — the second /build request with output.type set to markdown completes the flow. The PDF-to-Markdown API guide documents the full OCR-then-convert flow.

    When to use the Data Extraction API instead

    Processor API Markdown is the right tool when Markdown is simply the output format of a conversion. For retrieval-augmented generation (RAG)-grade extraction — layout-aware structure, tables and key-value pairs, bounding boxes, schema-shaped JSON, or citations and confidence scores — use the Data Extraction API. The engine tradeoffs are compared in Document AI vs. traditional OCR.

    Start a free trial Talk to our team

    FAQ

    Why convert a PDF to Markdown for LLMs?

    Markdown is plain text with lightweight structural cues, so an LLM receives clean headings, lists, and tables instead of a fixed visual layout. This reduces parsing errors and hallucinations compared with feeding a raw PDF.

    Does the Processor API convert scanned PDFs to Markdown directly?

    Conversion works best on born-digital PDFs with selectable text. For scanned or image-only PDFs, run OCR first to create a searchable PDF. Then convert that result to Markdown.

    How is this different from the Data Extraction API?

    The Processor API produces Markdown as an output format in a conversion workflow. The Data Extraction API adds layout-aware, RAG-grade extraction — typed elements, tables, bounding boxes, schema-shaped JSON, and confidence scores.

    Can only part of a PDF be converted?

    Yes. Add a zero-based pages range to the part. The end value is inclusive, so a range of 0–2 converts the first three pages.

    For the no-code and agentic paths to the same conversion, refer to our blog about teaching LLMs to read PDFs and the PDF-to-Markdown skill.

    Hulya Masharipov

    Hulya Masharipov

    Technical Writer

    Hulya is a frontend web developer and technical writer who enjoys creating responsive, scalable, and maintainable web experiences. She’s passionate about open source, web accessibility, cybersecurity privacy, and blockchain.

    Explore related topics

    50 free credits Start converting PDF to Markdown