fast-web-md-extract
Extract web page content as clean Markdown. Tries a fast HTTP request first, falls back to a Camoufox browser for anti-bot-protected sites.
Install
pip install fast-web-md-extract
Quick start
CLI
# Extract a single URL
fwm https://docs.python.org/3/tutorial/classes.html
# Extract multiple URLs
fwm https://example.com https://docs.python.org
# Save to a specific directory
fwm https://example.com -o my_output
# Extract from a file of URLs
fwm -f urls.txt
# Enable verbose logging
fwm https://example.com -v
# Use fast mode (skip fallback extraction)
fwm https://example.com --fast
Python (Async)
import asyncio
from fast_web_md_extract import Extractor
async def main():
async with Extractor() as ex:
result = await ex.extract("https://docs.python.org/3/tutorial/classes.html")
print(result.markdown[:200])
asyncio.run(main())
Python (Sync)
from fast_web_md_extract import Extractor
with Extractor() as ex:
result = ex.extract_sync("https://docs.python.org/3/tutorial/classes.html")
print(result.markdown[:200])
Save to file
# Markdown (default)
result.save("output/page.md")
# Plain text (strips Markdown syntax)
result.save("output/page.txt", fmt="txt")
Batch extract
async with Extractor() as ex:
results = await ex.extract_many([
"https://example.com",
"https://docs.python.org",
])
for r in results:
if r.markdown:
r.save(f"output/{r.url.split('/')[2]}.md")
Configuration
Extractor(
headless=True, # Run browser headless (default True)
timeout=15, # Cloudflare challenge timeout in seconds
min_content=1000, # Min chars to accept from fast path
concurrency=3, # Max concurrent browser pages
http_concurrency=50, # Max concurrent HTTP requests
fast=False, # Use trafilatura fast mode
)
How it works
- Fast path (httpx) — plain HTTP GET, no browser needed. Works for static sites like Wikipedia, Python Docs, blogs. Uses connection pooling and high concurrency (50 concurrent requests).
- Slow path (Camoufox) — launches a stealth browser to bypass Cloudflare and other anti-bot protection. Automatic fallback when the fast path is blocked or returns too little content.
- Content extraction (trafilatura + html-to-markdown) — trafilatura auto-detects main content first. Falls back to html-to-markdown for pages where trafilatura strips links or returns too little content.
Benchmark
Measured on Windows, Python 3.14, September 2026:
| Site | Type | Time | Chars | Method |
|---|---|---|---|---|
| docs.python.org | Static | 0.7s | 36,732 | HTTP fast path |
| th.wikipedia.org | Static | 4.1s | 293,464 | HTTP fast path |
| bbc.com | JS-rendered | 49.7s | 43,445 | Browser fallback |
| fao.org (Cloudflare) | Protected | 57.7s | 29,602 | Browser + html-to-markdown |
Static sites: ~1-4s | Protected sites: ~20-60s
CLI benchmark
$ fwm https://docs.python.org/3/tutorial/classes.html https://th.wikipedia.org/wiki/ประเทศไทย
Extracting: 100%|██████████| 2/2 [00:04<00:00, 2.05s/url]
0.7s OK: 36,732 chars -> output/docs.python.org.md
4.1s OK: 293,464 chars -> output/th.wikipedia.org.md
2/2 extracted successfully.
License
MIT
Metadata
Release files for fast-web-md-extract 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fast_web_md_extract-0.1.0.tar.gz | 145.6 kB | Without provenance | Details for fast_web_md_extract-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fast_web_md_extract-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for fast_web_md_extract-0.1.0-py3-none-any.whl |
Total release size: 157.5 kB
Release files / fast_web_md_extract-0.1.0.tar.gz
| Download URL | fast_web_md_extract-0.1.0.tar.gz |
|---|---|
| Size | 145.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
39d43e111862e1184984c62f6707587bc4dcc12bb130d0a67b8a6ab047c46858
|
|
BLAKE2b-256 checksum How to use checksums |
a8356fdc8576bff2471677ab360444069d41d3120d63629a36a4c1ec9629722b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / fast_web_md_extract-0.1.0-py3-none-any.whl
| Download URL | fast_web_md_extract-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec66dffb78776d0ed6b47c089f4f25f767f38f94ac589e3c26416ddc23e810e1
|
|
BLAKE2b-256 checksum How to use checksums |
d11bc69e7fee4c0dba768cf05b55e09b1f31ad80c1163b3ca01e5a9cad741dec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for fast-web-md-extract 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.