@trendtech33566: [Saved Version] For those who want to turn URLs or PDFs into clean Markdown PullMD, about 400. Here's what it can do ・C…
Summary
PullMD is an open-source, self-hostable service that converts web pages, PDFs, Office documents, EPUBs, images, audio, and YouTube videos into clean Markdown, with a REST API, MCP server, and PWA frontend.
View Cached Full Text
Cached at: 08/05/26, 12:23 PM
[Saved Version] For those who want to turn URLs or PDFs into clean Markdown: PullMD, about 400 (stars). Here’s what it can do:
- Convert web pages to Markdown without ads or decorations
- Supports PDF/Office/EPUB/images/audio/YouTube and more
- Includes REST API / MCP server / PWA
- Self-hostable, and easy to integrate with AI agents
An open-source project that instantly takes care of “standardizing information in Markdown.” It’ll resonate with people building RAG preprocessing or AI workflows.
What’s new in v3
PullMD v3 grows from a web-page reader into a general anything-to-Markdown service for agents, with a leaner default output. Everything beyond plain web extraction is opt-in and degrades gracefully - left unconfigured, v3 handles web pages exactly like v2, just with a cleaner body by default.
- Clean body by default - the Markdown body is now just
# Title+ content. The source URL, fetch date, and all metadata moved into the YAML frontmatter, so nothing is duplicated and you spend fewer tokens. Reddit posts follow the same rule: subreddit, author, upvotes, and publish date live in the frontmatter (subreddit,author,upvotes,published), not the body. This is the one breaking change: setPULLMD_SOURCE_HEADER=trueto restore the old inline header, and usePULLMD_FRONTMATTER_FIELDSto trim which fields are emitted. SeeMIGRATION.md. - Documents → Markdown - PDF, Word, PowerPoint, Excel, EPUB and more, by URL or upload (
POST /api/file, drag-and-drop in the PWA). - High-quality PDF tables (OCR) - an opt-in, vendor-neutral OCR tier (
?pdf=ocr) for table-grade PDF conversion, with automatic fallback to the free path. - Images & audio → Markdown - opt-in captioning and transcription via any OpenAI-compatible or local model; runs inside pullmd, no extra container required.
- YouTube transcripts - title, description and transcript with clickable timecodes, no API key required.
- Richer frontmatter - extraction source, quality, and (for media/OCR) model + token/page usage for cost tracking, plus a configurable field allowlist.
Self-hosters upgrading from v2.x: the clean-body change is the only breaking one -
MIGRATION.mdhas the one-line opt-out. Everything else is additive.
Added in the 3.x line since then:
- Hacker News pipeline (3.1) - items, comment permalinks and listings through a purpose-built converter, plus Web Share and an instant frontmatter toggle in the PWA.
X-Transcript-Status(3.2) - tells a transient YouTube rate-limit apart from a genuinely missing transcript.- SSRF protection (3.3) - private, loopback, link-local, CGNAT and cloud-metadata targets are rejected by default, on every fetch path and every redirect hop.
- Query-scoped extraction (3.4) -
?query=returns only the sections relevant to a question, with amax_tokensbudget. - Site recipes opened up (3.5/3.6) - JSON-LD-to-frontmatter, a contributor guide, and
select.contentso a recipe can name the article body outright. - Coverage guard (3.7) - recovers pages where extraction kept only a sliver of the body; see
PULLMD_COVERAGE_GUARD. - Account controls (3.8) - a non-admin can clear entries from their own history, self-registration can be closed with
PULLMD_ALLOW_SIGNUP, andscripts/admin.js create-usercreates accounts from the shell. - Download button (3.9) - the PWA saves a result as a
.mdfile, named by the server viaX-Suggested-Filenameand optionally date-prefixed.
Configuration
All variables go in .env (copy from .env.example):
v3.0.0 output format change: the markdown body is clean by default - just
# Titlefollowed by content. The source URL, fetch date, and all extraction metadata remain in the YAML frontmatter unchanged - the body no longer duplicates them. SetPULLMD_SOURCE_HEADER=trueto restore the old inline header. UsePULLMD_FRONTMATTER_FIELDSto pick which frontmatter fields are emitted (handy for trimming tokens in agent pipelines).
| Variable | Required | Purpose |
|---|---|---|
HOST_DOMAIN | Traefik variant only | Public hostname without scheme. Used by Traefik routing and as fallback for PUBLIC_URL. Unused by the default compose. |
PUBLIC_URL | no | Full public origin embedded in /help and the skill zip. Defaults to https://${HOST_DOMAIN}. |
TRAFILATURA_URL | no | URL of the Trafilatura sidecar’s /extract endpoint. Unset → skip Trafilatura, Readability only. |
PLAYWRIGHT_URL | no | URL of the Playwright sidecar’s /render endpoint. Unset → skip Playwright fallback for JS pages. |
MARKITDOWN_URL | no | URL of the MarkItDown sidecar’s /convert endpoint. Unset → document-conversion path disabled; POST /api/file returns 502. |
PULLMD_VISION_API_KEY / ..._BASE_URL / ..._MODEL | no | Image captioning via an OpenAI-compatible vision endpoint. Enabled when the key is set. _MODEL defaults to gpt-4o-mini. |
PULLMD_STT_API_KEY / ..._BASE_URL / ..._MODEL | no | Audio transcription via an OpenAI-compatible /audio/transcriptions endpoint. Enabled when the key is set. _MODEL defaults to whisper-1. |
PULLMD_LLM_API_KEY / ..._BASE_URL | no | Shared fallback credentials for vision + STT when the per-modality vars are unset. Key and base URL only - there is no PULLMD_LLM_MODEL, and setting one is ignored (the server warns at startup). |
PULLMD_PDF_OCR_API_KEY / ..._BASE_URL / ..._MODEL | no | Opt-in high-quality PDF→Markdown via an OCR provider that preserves tables (reference: Mistral OCR mistral-ocr-latest). Triggered per request with ?pdf=ocr or a recipe fetch.pdf: ocr. Default PDF handling stays the free markitdown path. _MODEL defaults to mistral-ocr-latest. |
MARKITDOWN_YOUTUBE | no | Set to true to route YouTube URLs through the markitdown sidecar (returns title + description + transcript). No API key required. Default: off. |
MARKITDOWN_YT_TIMECODES | no (sidecar) | Default timecode format in transcripts: links (YouTube timestamp links, default), plain (bare [MM:SS] labels), none (transcript text only). Overridable per-request via ?yt_timecodes=. |
MARKITDOWN_YT_CHUNK | no (sidecar) | Transcript block size in seconds (default 30). 0 keeps the original per-snippet granularity. Overridable per-request via ?yt_chunk=. |
MARKITDOWN_YT_LANGS | no (sidecar) | Comma-separated preferred transcript languages (e.g. de,en). Falls back to the first available language if none of the preferred ones exist. |
MARKITDOWN_YT_PROXY | no (sidecar) | HTTP(S) proxy URL for YouTube requests. Datacenter IP addresses are often rate-limited by YouTube’s transcript API; a residential or ISP proxy can help. |
REDDIT_CLIENT_ID | no | OAuth credentials for Reddit. Without them, PullMD uses the public JSON API (lower rate limit). |
REDDIT_CLIENT_SECRET | no | |
REDDIT_USER_AGENT | no | Reddit requires a unique UA. Default: PullMD/1.0 (URL-to-Markdown service). |
DISABLE_PUBLIC_HISTORY | no | When true, hides the global recent-conversions list and archive (/api/history + /api/archive return 403, frontend hides the section). /s/:id share links keep working. Default: false. |
PULLMD_USER_AGENT | no | Pin a single outbound User-Agent for every web fetch. Disables rotation. Useful for CI or when one specific UA is known to work. |
PULLMD_UA_FEED_URL | no | URL of a JSON feed of current real-world UAs. Default: WinFuture23/real-world-user-agents (https://github.com/WinFuture23/real-world-user-agents). Set to an empty string to disable live refresh and rely on the built-in seed pool. |
PULLMD_AUTH_MODE | no | disabled (default) / single-admin / multi-user. See “Authentication” below. |
PULLMD_ALLOW_SIGNUP | no | Self-registration in multi-user mode. Default: on. false / 0 / no / off closes /signup (404) and removes the “create an account” link from the login page. Accounts can still be created with node scripts/admin.js create-user . |
PULLMD_ADMIN_EMAIL | required when AUTH_MODE != disabled, on first startup | Bootstrap email for the first admin user. |
PULLMD_ADMIN_PASSWORD | required when AUTH_MODE != disabled, on first startup | Bootstrap password (min 8 chars). |
PULLMD_AUTH_TOKEN | no | Legacy bearer token compat (single-admin mode only, deprecated). |
PULLMD_SOURCE_HEADER | no | Set to true to restore the legacy inline source header in the body (# Title + **domain** · date + url; for Reddit the **r/sub** · u/user · N ↑ line). Default (unset): clean body - just the H1 title; source/date/post meta live in the frontmatter. |
PULLMD_FRONTMATTER_FIELDS | no | Comma-separated allowlist of frontmatter fields to emit (e.g. title,url,source,llm_tokens). Unset = all fields. Trims tokens. Unknown names are ignored with a startup warning. |
| `PULLMD |
Similar Articles
@tom_doerr: Converts web URLs, PDFs, and media files into clean Markdown, automatically stripping ads and navigation while supporti…
PullMD is a self-hosted URL-to-Markdown service for humans and AI agents, converting web pages, PDFs, and media files into clean Markdown, with support for an MCP server and Claude Code skill.
@GitHub_Daily: Trying to feed webpage content to AI, but ending up with a bunch of navigation bars, ads, and garbled text, wasting most of the context window, and AI still can't understand it. So I found this open-source project PullMD, which can extract any webpage content and convert it into clean Markdown files. Just provide a URL, auto-detect page type, layer by layer...
PullMD is an open-source URL to Markdown service that automatically extracts the main content of a webpage, removing navigation, ads, and other clutter. It supports headless browsers and multiple interfaces (web, REST API, MCP), making it easy for AI tools and users to obtain clean webpage text.
@DanKornas: Copying web pages into LLMs shouldn’t mean dragging along the whole browser. .MD this page is a browser extension that …
.MD this page is an open-source browser extension that converts web pages into clean, LLM-ready Markdown using Mozilla's Readability, with features like one-click capture, preview, and export.
@HowToPrompt__: Someone open-sourced a tool that converts pdfs to markdown at 122 pages per second. → PDFs, DOCX, PPTX, XLSX, EPUB, ima…
An open-source tool converts PDFs, DOCX, PPTX, XLSX, EPUB, and images to markdown at 122 pages per second, supporting tables, equations, and forms on GPU, CPU, or Mac.
tweet.md
tweet.md is a tool that converts X (Twitter) posts into clean Markdown format, simplifying content repurposing.