Key Takeaways
- SearchCans Reader API (
POST /api/url) converts any live URL to clean, LLM-ready Markdown in ~2–4s — usemode: 1for JavaScript-rendered SPAs,mode: 0for static pages - The deprecated
bparameter is removed — replace"b": Trueor"b": "true"with"mode": 1in all existing code.bis silently ignored and headless rendering will not trigger - File Extraction API (
POST /api/file) extends the same workflow to PDF, DOCX, and XLSX — turn offline documentation into searchable, LLM-ready Markdown without any local parsing library - Token savings: clean Markdown reduces LLM input tokens by ~78% vs raw HTML — for a knowledge base of 500 documents, this reduces daily LLM processing costs from ~$21 to ~$4.60 at GPT-4o pricing
Introduction
As developers, we love writing code, but we hate writing documentation.
We spend hours building a feature, only to leave the README.md blank or copy-paste messy HTML into our Obsidian notes. In 2026, manual formatting is a productivity killer. Whether you are building a Deep Research Agent or just archiving technical articles, you need a way to turn the chaotic web into clean, structured Markdown automatically.
The Solution? A programmatic Web-to-Markdown pipeline.
In this guide, we will build a Python tool that scrapes any URL, strips away the ads/boilerplate, and saves a perfect Markdown file for your docs or LLM training data.
Why Markdown is the "Universal API" for Knowledge
Markdown isn’t just a styling language; it is the lingua franca of AI.
The Documentation Crisis
Most "HTML-to-Markdown" converters are stuck in 2015. They leave behind messy <div> tags, broken tables, and base64 images that bloat your git history.
The Result: Noisy RAG Pipelines
Your RAG pipeline chokes on noise when fed poorly formatted content.
The Fix: Browser-Based Rendering
You need a "Reader API" that renders the page like a browser (handling React/Vue) before extracting the content.
Automating the "Boring Stuff"
Imagine triggering a workflow every time you star a GitHub repo or bookmark a blog post:
Step 1: Extract Main Content
Extract the main content while ignoring navbars and sidebars.
Step 2: Convert Code Blocks
Convert code blocks to standard fenced syntax (```python).
Step 3: Save to Your System
Save to your docs/ folder or Notion database.
Pro Tip: Obsidian Users
If you use Obsidian for your second brain, feeding it raw HTML clipping is useless for linking. Clean Markdown extraction allows you to use plugins like "Smart Connections" to find semantic links between your saved articles automatically.
Top Tools for Markdown Generation (2026 Comparison)
We tested the most popular tools for converting URLs to Markdown.
SearchCans Reader API
The developer’s choice for precision.
Best Feature: Browser Mode
Browser Mode (mode: 1) executes JavaScript before extraction via a headless browser, ensuring you get the actual content from Single Page Applications (SPAs). This replaced the deprecated b parameter in early 2026.
Pricing Model
Pay-As-You-Go with no monthly subscription trap.
Use Case
Perfect for automating daily digests and RAG data ingestion.
Jina Reader
Pros
Open source friendly with good URL prefix shortcuts.
Cons
Rate limits can be restrictive for bulk processing; less control over wait times for dynamic sites.
Pandoc
Pros
The classic CLI tool for file conversion.
Cons
Struggles with fetching live URLs; primarily for local file-to-file conversion (e.g., Docx to Markdown).
Feature Breakdown
| Feature | SearchCans | Jina | Pandoc |
|---|---|---|---|
| Dynamic JS Support | Yes (Headless Browser) | Limited | No |
| API Integration | Python/JS/n8n | HTTP | CLI |
| Table Formatting | Perfect (GFM) | Good | Variable |
| Pricing Model | Pay-As-You-Go | Freemium | Free (Local) |
Tutorial: Build a "Readme Generator" Script
The following Python script takes a list of URLs (e.g., competitor documentation or tech blogs) and saves them as clean Markdown files locally.
We will use the SearchCans Reader API (/api/url) which is optimized for this exact task.
Prerequisites
Before running the script:
- Python 3.x installed
requestslibrary (pip install requests)- A SearchCans API Key
Python Implementation: Markdown Clipper
This script converts URLs to clean Markdown files with metadata headers.
# src/tools/markdown_clipper.py
import requests
import json
import os
import re
# Configuration
API_KEY = "YOUR_SEARCHCANS_KEY"
BASE_URL = "https://www.searchcans.com/api/url"
OUTPUT_DIR = "./knowledge_base"
def sanitize_filename(title):
"""Clean title to be a valid filename"""
return re.sub(r'[\\/*?:"<>|]', "", title)[:50] + ".md"
def url_to_markdown(target_url):
"""
Converts a single URL to a Markdown file using SearchCans.
"""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
print(f"📄 Processing: {target_url}...")
# Payload parameters for Reader API:
# s: Source URL to extract
# t: Type ("url" for web pages)
# w: Wait time in ms before extraction (3000ms for heavy JS sites)
# mode: 0=standard HTTP (2 credits), 1=headless browser (4 credits)
# d: API processing timeout in ms
payload = {
"s": target_url,
"t": "url",
"w": 3000,
"mode": 1, # Use headless browser for SPAs (React, Vue, Next.js)
"d": 15000 # 15s timeout for JS-heavy pages
}
try:
# High timeout to allow browser rendering
response = requests.post(
BASE_URL,
headers=headers,
json=payload,
timeout=30
)
result = response.json()
if result.get("code") == 0:
# Handle data extraction
data = result.get("data", {})
# Normalize if API returns stringified JSON
if isinstance(data, str):
try:
data = json.loads(data)
except:
pass
if isinstance(data, dict):
content = data.get("markdown", "")
title = data.get("title", "Untitled")
return title, content
print(f"❌ API Error: {result.get('msg')}")
return None, None
except Exception as e:
print(f"❌ Network Error: {str(e)}")
return None, None
if __name__ == "__main__":
# Create output folder
if not os.path.exists(OUTPUT_DIR):
os.makedirs(OUTPUT_DIR)
# List of URLs to archive
urls_to_clip = [
"https://react.dev/learn",
"https://stripe.com/docs/api"
]
for url in urls_to_clip:
title, markdown = url_to_markdown(url)
if markdown:
filename = sanitize_filename(title)
path = os.path.join(OUTPUT_DIR, filename)
# Add Metadata header for Obsidian/Jekyll
full_content = f"# {title}\n\n**Source:** {url}\n\n---\n\n{markdown}"
with open(path, "w", encoding="utf-8") as f:
f.write(full_content)
print(f"✅ Saved: {filename}")
Pro Tip: Clean Context for LLMs
If you are building a coding assistant using Context Window Engineering, never paste raw documentation code. Use this script to "flatten" the docs into a single Markdown file. This reduces token usage by 40% compared to raw copy-pasting.
Extending to Documents: File Extraction API [F]
The same Markdown-first workflow extends beyond live URLs to offline documents. Technical knowledge bases often contain PDF datasheets, DOCX technical specifications, and XLSX data tables. Parsing these locally requires PyMuPDF, python-docx, or openpyxl — each with different APIs and output quality.
SearchCans File Extraction API (POST /api/file) handles PDF, DOCX, and XLSX conversion server-side, returning the same clean Markdown format as the Reader API.
Python: Unified Document + URL Knowledge Base Builder
# knowledge_base_builder.py
# Combines URL extraction (Reader API) + File extraction (File API)
import requests
import os
API_KEY = "YOUR_SEARCHCANS_KEY"
READER_URL = "https://www.searchcans.com/api/url"
FILE_URL = "https://www.searchcans.com/api/file"
OUTPUT_DIR = "./knowledge_base"
def extract_file_to_markdown(file_path: str) -> tuple:
"""Convert PDF/DOCX/XLSX to Markdown using File Extraction API."""
headers = {"Authorization": f"Bearer {API_KEY}"}
filename = os.path.basename(file_path)
with open(file_path, "rb") as f:
files = {"file": (filename, f)}
resp = requests.post(FILE_URL, headers=headers, files=files, timeout=30)
data = resp.json()
if data.get("code") == 0:
page_data = data.get("data", {})
return page_data.get("title", filename), page_data.get("markdown", "")
return None, None
# Example: process a mixed batch of URLs and local files
SOURCES = [
{"type": "url", "src": "https://react.dev/learn"},
{"type": "url", "src": "https://stripe.com/docs/api"},
{"type": "file", "src": "./docs/api-reference.pdf"},
{"type": "file", "src": "./docs/architecture.docx"},
]
os.makedirs(OUTPUT_DIR, exist_ok=True)
for source in SOURCES:
if source["type"] == "url":
title, markdown = url_to_markdown(source["src"]) # from Markdown Clipper above
else:
title, markdown = extract_file_to_markdown(source["src"])
if markdown:
slug = re.sub(r'[^a-z0-9]+', '-', title.lower())[:50]
path = os.path.join(OUTPUT_DIR, f"{slug}.md")
with open(path, "w", encoding="utf-8") as f:
f.write(f"# {title}\n\n**Source:** {source['src']}\n\n---\n\n{markdown}")
print(f"Saved: {slug}.md")
This unified pipeline means your knowledge base builder handles all content types through one API account, one billing system, and one response schema. No local dependencies for document parsing.
Cost estimate: Processing a 500-document knowledge base (mix of URLs and PDFs) using Reader API (mode: 0) and File Extraction API costs approximately $0.56–$1.12 per 1,000 extractions — a one-time ingestion cost of $0.28–$0.56 for 500 documents.
SearchCans is NOT for processing documents from a local corporate intranet behind a VPN or authentication wall — those require direct access credentials the API cannot provide. SearchCans is the right tool for publicly accessible web URLs and file uploads.
FAQ: Developer Productivity
Can I use this for GitHub Actions?
Yes, absolutely. You can set up a GitHub Action that runs this Python script every night to archive your favorite blogs into a repo. The script can be triggered on a schedule or when you star a repository. SearchCans’ Pay-As-You-Go pricing makes this incredibly cheap since you only pay when the action runs, with no wasted monthly credits.
How does this handle images?
The SearchCans Reader API preserves image links in standard Markdown syntax . This means your local Markdown file will still render the images directly from the source server. If you need to download images locally, you can extend the script to fetch and save them to a local assets folder.
Is it better than html2text?
Python libraries like html2text are fast but "dumb." They don’t execute JavaScript, so they often miss code blocks that are dynamically loaded (like Prism.js or Shiki). Our Reader API vs. Local Libraries benchmark shows that API-based rendering retrieves 35% more accurate code snippets from modern documentation sites.
Can I use this for GitHub Actions to auto-update documentation?
Yes. Set up a GitHub Action that runs this Python script on a schedule or when you push to a specific branch. SearchCans’ Pay-As-You-Go pricing means you only pay for actual extractions — no wasted monthly credits when the Action doesn’t run. See the complete RAG pipeline guide for production architecture.
How does this handle PDF and DOCX files?
Use the File Extraction API (POST /api/file) — upload the file as a multipart form, receive clean Markdown in return. The same data.markdown field in the response contains the extracted text with tables preserved as GFM Markdown tables.
Conclusion
Documentation should not be a chore. By treating web content and documents as data that can be fetched and converted programmatically, you eliminate the manual formatting bottleneck that slows every developer knowledge base.
Whether you are automating a personal Obsidian vault, feeding a RAG agent, or building a team documentation system, the ability to turn any URL or document into clean Markdown is a foundational capability in 2026. The Reader API and File Extraction API cover both live web content and offline documents through a single API account.
Get your SearchCans API Key and start building →
Frequently Asked Questions
Q: What is the difference between SearchCans Reader API and a standard web scraper for building a knowledge base?
A: A standard web scraper returns raw HTML, which requires custom parsing logic for every site structure and breaks whenever a site updates its layout. The SearchCans Reader API (POST /api/url) returns clean, structured Markdown regardless of the source site — no custom parser, no selector maintenance. For knowledge base workflows, this means consistent output format across all sources, which is critical when feeding content to an LLM or vector database.
Q: How does the File Extraction API handle PDFs versus web URLs, and when should I use each?
A: Use POST /api/url (Reader API) for live web pages — it handles dynamic JavaScript rendering via mode: 1. Use POST /api/file (File Extraction API) for static documents — PDFs, DOCX, XLSX — that cannot be fetched via URL. The File Extraction API converts documents to Markdown optimized for LLM ingestion, preserving tables, headings, and structured data. In a mixed knowledge base (web articles + PDF reports), both APIs write to the same Markdown format, so your downstream pipeline is unified.
Q: What SearchCans plan do I need for an automated daily knowledge base workflow?
A: It depends on volume. A workflow syncing 50 URLs per day (one run) needs only 1 Parallel Lane (Standard plan at $18, 20K credits). For teams running continuous sync — say 500 URLs/hour across 10 topics — Pro plan (22 Parallel Lanes, ~1M credits/month at $597) provides the concurrency to run all fetches in parallel in under 3 minutes rather than 45+ minutes sequentially. The key metric is not hourly request caps (SearchCans has none) but Parallel Lanes — simultaneous in-flight requests.