Convert any URL into clean, token-efficient Markdown for LLMs. One thing, done well.
Project description
url2md4ai
Convert any URL into clean, token-efficient Markdown for LLMs.
uv tool install url2md4ai # or: pip install url2md4ai
url2md4ai https://en.wikipedia.org/wiki/Markdown
Feed web pages to an LLM without paying for navigation menus, cookie banners, ads and scripts. url2md4ai fetches a page, extracts the main content and emits structured Markdown — headings, text, tables, lists, code blocks, image alt text — typically cutting raw page size by more than 90%.
---
title: "Markdown - Wikipedia"
source: https://en.wikipedia.org/wiki/Markdown
fetched: 2026-06-10
---
# Markdown
**Markdown** is a lightweight markup language for creating formatted text...
CLI
url2md4ai https://example.com/article # markdown on stdout
url2md4ai --no-links https://example.com/article # drop link URLs, keep text (saves tokens)
url2md4ai --no-frontmatter https://example.com # body only
url2md4ai --render https://example.com/spa # force JavaScript rendering (js extra)
url2md4ai -v https://example.com # extraction strategy on stderr
MCP server (for agents)
Install with the mcp extra and register the stdio server in your MCP client (Claude Code, Claude Desktop, ...):
uv tool install "url2md4ai[mcp]"
{
"mcpServers": {
"url2md4ai": { "command": "url2md4ai-mcp" }
}
}
The server exposes a single tool: url_to_markdown(url, include_links=true, render=false).
Python library
from url2md4ai import to_markdown, html_to_markdown
md = to_markdown("https://example.com/article")
md = to_markdown("https://example.com/article", include_links=False, timeout=30)
# already have the HTML? (cache, your own renderer, ...)
md = html_to_markdown(html, base_url="https://example.com/article")
Errors are explicit and typed: FetchError (network / HTTP status), UnsupportedContentError (PDF, images, JSON...), ExtractionError (empty or paywalled pages) — all subclasses of Url2md4aiError.
JavaScript pages
The core package uses static fetching only, which covers most articles, docs and blogs with zero browser overhead. For pages that only exist after client-side rendering, install the js extra:
pip install "url2md4ai[js]"
playwright install chromium
- With the extra installed, rendering kicks in automatically when static extraction finds nothing (
render="auto", the default). - Some pages serve partial static content and load the rest client-side (embedded job boards, widgets). No heuristic can detect that reliably, so force rendering when you know you need it:
--renderon the CLI,render="force"in Python,render=trueon the MCP tool. - Content-bearing iframes are included in the result; tracker frames, images, media and fonts are skipped.
How it works
- Fetch — plain HTTP GET (httpx, redirects followed, 10 MB cap). Markdown and plain-text responses are returned as-is; PDFs and other binaries fail fast with a clear error.
- Extract — trafilatura, precision-first. If precision mode finds too little it retries favoring recall, then reads the page's JSON-LD structured data (many JavaScript-heavy sites ship their content there for SEO), then optionally renders JavaScript, then falls back to whole-page text before giving up.
- Post-process — whitespace normalization, decorative images without alt text dropped, optional link stripping, YAML frontmatter (
title,source,fetched).
Philosophy
- One thing well: URL in, LLM-ready Markdown out. No crawling, no screenshots, no LLM calls.
- Token efficiency is the metric: every byte in the output should inform the model.
- Lean by default: 2 runtime dependencies; browsers and MCP are opt-in extras.
Development
uv sync --all-extras
uv run pytest
uv run ruff check && uv run ruff format --check
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file url2md4ai-2.1.0.tar.gz.
File metadata
- Download URL: url2md4ai-2.1.0.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
82d6d1b8cdeea989bbe2ab3e60db1e610a63241b4f03f73cc855043f28678036
|
|
| MD5 |
a3438ef6c95887e210f61455bc4092c8
|
|
| BLAKE2b-256 |
a193521aac30dfbd35b31fedcea7d868e7e36a29b72a1f9660a20cfe91826020
|
File details
Details for the file url2md4ai-2.1.0-py3-none-any.whl.
File metadata
- Download URL: url2md4ai-2.1.0-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e4e9e80ef97a492800ee09d7855366e92811056d24fd0873df5b263f159b59c
|
|
| MD5 |
b0d30300503c694293dbbb45b430a2ac
|
|
| BLAKE2b-256 |
de309dac4af46454b1a56ffd294e9d75f41a01cb5f6ef5ba66c350a4f33d03f2
|