Skip to main content

Markdrop Logo

Markdrop

Downloads PyPI Version License Stars Issues Forks

A Python package for converting PDFs to structured Markdown and interactive HTML, with AI-powered image and table descriptions across six major LLM providers. Available on PyPI.


Features

  • PDF → Markdown conversion with formatting preservation (via Docling)
  • Automatic image extraction using XRef IDs
  • Table detection using Microsoft's Table Transformer
  • PDF URL support
  • AI-powered image and table descriptions — 6 providers: Gemini, OpenAI, Anthropic Claude, Groq, OpenRouter, LiteLLM
  • Interactive HTML output with downloadable Excel tables
  • Customisable image resolution and UI elements
  • Structured logging (never pollutes your app's root logger)

Installation

Core install (PDF conversion + Gemini/OpenAI):

pip install markdrop

With Anthropic Claude:

pip install "markdrop[anthropic]"

With Groq:

pip install "markdrop[groq]"

With LiteLLM (routes to 100+ providers):

pip install "markdrop[litellm]"

Everything (including local HuggingFace models):

pip install "markdrop[all]"

Faster CPU / lightweight Markdown (--fast mode):

pip install "markdrop[lite]"
markdrop convert report.pdf --output_dir out --fast

See docs/cpu-guide.md for CPU-only and Colab guidance.

OpenRouter is accessed through the openai package (already included in core), so no extra install is needed.


Supported AI Providers

Provider --ai_provider Default vision model Default text model (tables) Vision
Google Gemini gemini gemini-3.1-flash-lite gemini-3.1-flash-lite
OpenAI openai gpt-5.6-terra gpt-5.6-luna
Anthropic Claude anthropic claude-opus-5 claude-sonnet-5
Groq groq meta-llama/llama-4-maverick-17b-128e-instruct meta-llama/llama-4-scout-17b-16e-instruct
OpenRouter openrouter google/gemini-3.1-flash-lite anthropic/claude-sonnet-5
LiteLLM litellm openai/gpt-5.6-terra openai/gpt-5.6-luna

All models are configurable — use --model to override for any provider, or set model_name_override in ProcessorConfig.


Quick Start

See examples/quickstart.md for copy-paste commands.

Open in Colab Watch the demo


CLI Usage

Check the installed version:

markdrop --version

1. Convert PDF → Markdown + HTML

markdrop convert <input_path> --output_dir <dir> [--add_tables] [--fast]
# Example
markdrop convert report.pdf --output_dir out --add_tables
# Outputs: out/report-markdroped.md and out/report-markdroped.html

# Also works with URLs (SSRF-protected download):
markdrop convert https://arxiv.org/pdf/1706.03762 --output_dir out

2. Generate AI Descriptions for Images & Tables

markdrop describe <markdown_file> --ai_provider <provider> [--output_dir <dir>] [--remove_images] [--remove_tables]
Provider --ai_provider
Google Gemini gemini
OpenAI openai
Anthropic Claude anthropic
Groq groq
OpenRouter openrouter
LiteLLM litellm
# Gemini (default)
markdrop describe doc.md --ai_provider gemini

# Anthropic Claude
markdrop describe doc.md --ai_provider anthropic --remove_images

# Groq (fastest inference)
markdrop describe doc.md --ai_provider groq

# OpenRouter (any model)
markdrop describe doc.md --ai_provider openrouter

# LiteLLM (unified gateway)
markdrop describe doc.md --ai_provider litellm

3. Set Up API Keys

markdrop setup <provider>

Keys are stored in your user config directory (via platformdirs, with a fallback to ~/.config/markdrop/):

  • Linux/macOS: ~/.config/markdrop/.env (or $XDG_CONFIG_HOME/markdrop/.env)
  • Windows: %LOCALAPPDATA%\markdrop\.env

On POSIX systems, the .env file is written with 0o600 permissions.

markdrop setup gemini       # → GEMINI_API_KEY (GOOGLE_API_KEY also accepted)
markdrop setup openai       # → OPENAI_API_KEY
markdrop setup anthropic    # → ANTHROPIC_API_KEY
markdrop setup groq         # → GROQ_API_KEY
markdrop setup openrouter   # → OPENROUTER_API_KEY
markdrop setup litellm      # → LITELLM_API_KEY

4. Analyze Images in a PDF

markdrop analyze report.pdf --output_dir pdf_analysis --save_images

5. Batch Image Description Generation

markdrop generate images/ --output_dir descriptions/ --prompt "Describe in detail." \
  --llm_client gemini openai

Available --llm_client values: qwen, gemini, openai, llama-vision, molmo, pixtral


Python API

PDF Conversion

from markdrop import markdrop, MarkDropConfig, add_downloadable_tables
from pathlib import Path
import logging

config = MarkDropConfig(
    image_resolution_scale=2.0,
    download_button_color="#444444",
    log_level=logging.INFO,
    log_dir="logs",
    excel_dir="markdrop-excel-tables",
)

html_path = markdrop("path/to/input.pdf", "output", config)
downloadable_html = add_downloadable_tables(html_path, config)

AI Descriptions

import asyncio
from markdrop import process_markdown, ProcessorConfig, AIProvider, setup_keys

# One-time key setup (writes to user config ~/.config/markdrop/.env)
setup_keys("anthropic")

config = ProcessorConfig(
    input_path="out/report-markdroped.md",
    output_dir="output",
    ai_provider=AIProvider.ANTHROPIC,  # GEMINI | OPENAI | ANTHROPIC | GROQ | OPENROUTER | LITELLM
    remove_images=False,
    remove_tables=False,
    table_descriptions=True,
    image_descriptions=True,
    max_retries=3,
    retry_delay=2,
    # Override default models (all providers have matching config fields):
    anthropic_model_name="claude-opus-5",
    anthropic_text_model_name="claude-sonnet-5",
)

output_path = asyncio.run(process_markdown(config))

Using OpenRouter to access any model

config = ProcessorConfig(
    input_path="doc.md",
    output_dir="output",
    ai_provider=AIProvider.OPENROUTER,
    openrouter_model_name="meta-llama/llama-4-scout",  # any model on openrouter.ai/models
    openrouter_text_model_name="anthropic/claude-sonnet-5",
    openrouter_site_url="https://yoursite.com",
    openrouter_site_name="My App",
)

Using LiteLLM for any 100+ provider

import os

os.environ["ANTHROPIC_API_KEY"] = "..."  # set any provider's key

config = ProcessorConfig(
    input_path="doc.md",
    output_dir="output",
    ai_provider=AIProvider.LITELLM,
    litellm_model_name="anthropic/claude-opus-5",
    litellm_text_model_name="openai/gpt-5.6-luna",
)

Batch Image Description Generation

from markdrop import generate_descriptions

generate_descriptions(
    input_path="images/",
    output_dir="output/",
    prompt="Give a highly detailed description of this image.",
    llm_client=["gemini", "llama-vision"],
)

API Reference

ProcessorConfig – AI Provider Fields

Field Default Notes
gemini_model_name gemini-3.1-flash-lite Vision model
gemini_text_model_name gemini-3.1-flash-lite Text model
openai_model_name gpt-5.6-terra Vision
openai_text_model_name gpt-5.6-luna Tables / text
anthropic_model_name claude-opus-5 Vision
anthropic_text_model_name claude-sonnet-5 Text (cheaper)
groq_model_name meta-llama/llama-4-maverick-17b-128e-instruct Vision
groq_text_model_name meta-llama/llama-4-scout-17b-16e-instruct Text
openrouter_model_name google/gemini-3.1-flash-lite Any model string from openrouter.ai/models
openrouter_text_model_name anthropic/claude-sonnet-5
litellm_model_name openai/gpt-5.6-terra provider/model format
litellm_text_model_name openai/gpt-5.6-luna

MarkDropConfig

Field Default Notes
image_resolution_scale 2.0 Scale factor for extracted images
download_button_color '#444444' HTML button colour
log_level logging.INFO
log_dir 'logs'
excel_dir 'markdrop_excel_tables'

Contributing

We welcome contributions! See CONTRIBUTING.md. Please read our Code of Conduct.

git clone https://github.com/shoryasethia/markdrop.git
cd markdrop
python -m venv venv && source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -e ".[dev]"
ruff check .
pytest

Project Structure

markdrop/
├── setup.py
├── requirements.txt
├── README.md
└── markdrop/
    ├── __init__.py
    ├── main.py          ← CLI entry-point
    ├── process.py       ← PDF conversion
    ├── parse.py         ← AI description engine (all 6 providers)
    ├── helper.py        ← PDF image analysis
    ├── utils.py         ← PDF download helpers
    ├── setup_keys.py    ← Interactive API key manager
    ├── ignore_warnings.py
    ├── src/
    │   └── markdrop-logo.png
    └── models/
        ├── img_descriptions.py
        ├── model_loader.py  ← Local HF model loader
        ├── responder.py
        └── logger.py

License

GPL-3.0 — see LICENSE.

Changelog

See CHANGELOG.md.

Support

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

markdrop-4.1.1.tar.gz (55.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

markdrop-4.1.1-py3-none-any.whl (52.7 kB view details)

Uploaded Python 3

File details

Details for the file markdrop-4.1.1.tar.gz.

File metadata

  • Download URL: markdrop-4.1.1.tar.gz
  • Upload date:
  • Size: 55.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.11

File hashes

Hashes for markdrop-4.1.1.tar.gz
Algorithm Hash digest
SHA256 9ff1d299368d4c684ba4f00fb4124582d626e407af21f3d0643064f658863e4a
MD5 01e7c20932f0d97d30f4a5b33bce3a84
BLAKE2b-256 507d6f08b22c378eeb65b1dd994e7ad37c20804cd6113a0ab2cda83d8e129da4

See more details on using hashes here.

File details

Details for the file markdrop-4.1.1-py3-none-any.whl.

File metadata

  • Download URL: markdrop-4.1.1-py3-none-any.whl
  • Upload date:
  • Size: 52.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.11

File hashes

Hashes for markdrop-4.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ea28d200a0db9b605a1d4c86e6cab76b8f8aa40e4bda36fd7a485697385e0ab3
MD5 8c43e9be36c585dc34474ed2d5d3de2b
BLAKE2b-256 9e5d8426c619f66343c5b946d5246097b3e90ebb43286f37e98e6ccc843f96a2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page