We've all hit the same wall with read-later apps: you save an article to Pocket or Instapaper, and it works — right up until you want to actually use that content. Your notes are trapped inside someone else's silo, and the "clean view" is nice but it's not yours.
If you live in Obsidian (or any Markdown-based note system), you want something better: the article's clean content saved as plain Markdown into your vault — searchable, linkable, and permanent. The only thing standing in the way is turning a messy web page into clean Markdown.
That's exactly what the Web to Markdown/JSON API does. One HTTP call takes any URL and returns clean Markdown with the nav bars, ads, cookie banners, and scripts stripped away.
In this article you'll build your own web clipper that saves any page into your Obsidian vault as a proper note, in about 50 lines of Python.
The API at a glance
Endpoint:
POST https://web2md-api-production-d822.up.railway.app/extract
Request:
{
"url": "https://example.com/great-article",
"format": "markdown",
"max_length": 50000
}
-
format—markdown,json, ortext -
max_length— cap the response size (up to 50000 characters) - Free tier: 50 requests/day
- Sign up / grab a key on RapidAPI
Response:
{
"success": true,
"title": "The Great Article",
"content": "# The Great Article\n\n## Introduction\n\n...",
"description": "A summary of the article",
"word_count": 1523,
"response_time_ms": 210
}
The content field is clean Markdown — headings, paragraphs, lists, code blocks, nothing else. That's the whole game: your clipper gets an article that's already ready to live in Obsidian, instead of a pile of HTML you'd have to clean yourself.
The plan
-
POSTa URL to/extractand get Markdown back. - Wrap it in YAML frontmatter (title, source URL, date, tags).
- Sanitize the title into a filename.
- Save the file into your vault's Inbox folder.
The code
Save this as clip.py:
import re
import sys
from datetime import date
from pathlib import Path
import requests
API_URL = "https://web2md-api-production-d822.up.railway.app/extract"
VAULT = Path.home() / "Documents" / "Obsidian" / "Inbox" # your vault inbox
def fetch_markdown(url: str) -> dict:
"""Turn any web page into clean Markdown via the API."""
r = requests.post(
API_URL,
json={"url": url, "format": "markdown", "max_length": 50000},
timeout=30,
)
r.raise_for_status()
return r.json()
def slugify(title: str) -> str:
"""Turn an article title into a safe, readable filename."""
name = re.sub(r"[^\w\- ]+", "", title).strip().replace(" ", "-")
return (name[:80] or "untitled") + ".md"
def build_note(data: dict, url: str, tags: list[str]) -> str:
"""Wrap extracted Markdown in Obsidian-friendly frontmatter."""
frontmatter = "\n".join([
"---",
f"title: "\"{data['title']}\"\","
f"source: {url}",
f"clipped: {date.today().isoformat()}",
f"tags: [{', '.join(tags)}]",
"---",
"",
])
return frontmatter + data["content"]
def clip(url: str, tags: list[str]) -> Path:
"""Fetch a page and save it into the vault as a Markdown note."""
data = fetch_markdown(url)
note = build_note(data, url, tags)
VAULT.mkdir(parents=True, exist_ok=True)
out = VAULT / slugify(data["title"])
out.write_text(note, encoding="utf-8")
print(f"Saved: {out.name} ({data['word_count']} words)")
return out
if __name__ == "__main__":
url = sys.argv[1]
tags = sys.argv[2:] or ["clippings"]
clip(url, tags)
Run it
pip install requests
python clip.py https://example.com/great-article "reading" "tech"
The note lands in your vault, ready to be searched, linked, and edited:
---
title: "The Great Article"
source: https://example.com/great-article
clipped: 2026-09-07
tags: [reading, tech]
---
# The Great Article
## Introduction
...clean Markdown, no nav bars or ads...
Make it one click: a bookmarklet
A clipper you run from the terminal is fine, but a clipper you trigger with one click is a tool. Here's a tiny bookmarklet that fires off the same request and copies the Markdown to your clipboard:
javascript:(()=>{fetch("https://web2md-api-production-d822.up.railway.app/extract",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:location.href,format:"markdown"})}).then(r=>r.json()).then(d=>navigator.clipboard.writeText(d.content)).then(()=>alert("Markdown copied to clipboard"))})();
Drag it to your bookmarks bar, click it on any article, and paste straight into a new Obsidian note. No server, no setup — the API does the extraction, your browser does the rest.
For a fully automatic flow, point clip.py at a Raycast script, an Alfred workflow, or an iOS Shortcut that posts the shared URL to a tiny Flask endpoint running clip().
Why clean Markdown matters here
Obsidian is at its best when your notes are text you can actually read and grep. If you save raw HTML into your vault, you get garbage — inline styles, <div> soup, and tracking scripts polluting your search index. By clipping through the API, every note you save is already clean Markdown, which means:
- Full-text search finds your clipped articles by their content, not by markup.
- Backlinks and links work normally because the text is real Markdown.
- Syncing (iCloud, Syncthing, git) is tiny and fast — no bloated HTML.
The API's json format is also handy here: it returns structured paragraphs, headings, images, and links separately, so you can build richer notes — for example, auto-generating a ## Links or ## Images section from the structured output.
Taking it further
- Auto-tag — run the clipped text through a keyword check (or an LLM) to suggest tags before saving.
- Clip a whole reading list — feed the API a list of URLs and clip them all overnight (50 free requests/day covers a serious reading habit).
-
Use
format: "text"for a stripped, no-markup version when you just want the prose. -
Track your reading — append each clip's
word_countto a small CSV to see what you're actually consuming.
Wrapping up
Read-later apps are convenient, but they own your notes. Building your own clipper on the Web to Markdown/JSON API gives you the same one-click convenience with output that lives in your vault, in your format, forever.
Try it free — 50 requests/day on RapidAPI — and stop letting the read-later apps hold your articles hostage.
Top comments (0)