A Safari extension that saves any web page as clean Markdown — via right-click or a toolbar button.
- Right-click ▸ Save page as Markdown — extracts the readable article (via Mozilla Readability, stripping nav/ads/sidebars) and converts it to clean Markdown.
- Right-click ▸ Save selection as Markdown — appears when text is selected; saves just that selection, with formatting/links preserved.
- Toolbar button — opens a small Save page and downloads the article from the extension's own context, so it works even on sites that block in-page downloads (see Locked-down sites below).
Each save produces a .md file named after the page title, with a small header:
# Article Title
> Source: <https://example.com/article>
> Author: Jane Doe
> Saved: 2026-06-24
The article body, as Markdown…extension/ ← the web extension itself (this is what Safari loads)
manifest.json
background.js ← menu items + toolbar button; injects the worker on use
content.js ← extracts content and converts it to Markdown
save.html/save.js ← the toolbar button's Save page (does the download)
lib/ ← vendored Readability + Turndown (+ GFM plugin)
images/ ← icons
build.sh ← wraps extension/ into an Xcode project
install.sh ← builds a signed Release and installs it to /Applications
generate_icons.py ← regenerates the icon set (needs Pillow)
Safari only loads extensions that are wrapped in an app and built with Xcode, so there are a few one-time steps.
Prerequisite: macOS with Xcode installed (free, from the Mac App Store — the standalone Command Line Tools are not enough).
git clone https://github.com/ellewiz/markdown-clipper.git
cd markdown-clipper
./build.shThis runs Apple's safari-web-extension-converter and produces
xcode/Markdown Clipper/Markdown Clipper.xcodeproj. The script locates Xcode
automatically, even if xcode-select still points at the Command Line Tools, so
no sudo is needed.
Building your own copy? Change the bundle identifier near the bottom of
build.shto your own namespace (e.g.com.yourname.Markdown-Clipper) so it's unique to you. Keep the app and extension IDs consistent — see the comment inbuild.sh.
- Open the generated
.xcodeprojin Xcode. - With the Markdown Clipper scheme selected, press Run (⌘R). A tiny container app launches — you can quit it; building is what matters.
If Xcode shows a signing error, see Signing below.
- Safari ▸ Settings ▸ Advanced → enable "Show features for web developers".
- Safari ▸ Develop menu → Allow Unsigned Extensions (needed for local unsigned builds; it resets every time you quit Safari).
- Safari ▸ Settings ▸ Extensions → tick Markdown Clipper, then grant it website access (Always Allow on Every Website is simplest; it only ever reads a page when you actually pick a menu item).
The unsigned-build flow means re-enabling "Allow Unsigned Extensions" after every Safari restart. To make the extension stick permanently, sign it with a free Apple ID:
- In Xcode, select the project ▸ the Markdown Clipper target ▸ Signing & Capabilities.
- Tick Automatically manage signing and pick your Team (add your Apple ID under Xcode ▸ Settings ▸ Accounts if needed — a free Personal Team works).
- Repeat for the Markdown Clipper Extension target, using the same Team.
- Press Run (⌘R) again. The extension is now signed and survives restarts — no more toggling "Allow Unsigned Extensions".
If you hit "Failed to register bundle identifier", change the bundle ID to your own namespace (step 1) for both targets and rebuild.
Xcode's Run builds into a throwaway DerivedData cache — when that's cleaned,
the app (and the extension inside it) vanishes from Safari. Once you've set up
signing above, install a proper copy to /Applications instead:
./install.shThis builds a signed Release, copies the app to /Applications (so it survives
Xcode cleans and Safari restarts), and launches it once to register the extension.
Then enable it in Safari ▸ Settings ▸ Extensions. Re-run ./install.sh whenever
you change anything under extension/.
Right-click anywhere on a page → Save page as Markdown (or select text
first → Save selection as Markdown). A toast confirms the filename and the
.md lands in your Downloads folder.
Or click the toolbar button to open a small Save page, then Download .md.
Safari blocks extensions on privileged pages (Start Page, Settings, the Extensions gallery). Both actions do nothing there — that's expected.
Some sites (e.g. Yahoo) send a CSP sandbox that forbids the browser from
downloading anything from the page, and Safari has no extension downloads API
to work around it. The extension handles this honestly:
- Right-click detects the block and copies the Markdown to your clipboard
instead (the toast says so) — paste it into a new
.mdfile. - The toolbar button always saves a real file, because it downloads from the extension's own Save page, which the site's CSP can't touch. The first time, Safari asks "Do you want to allow downloads…?" — click Allow (it's a one-time prompt for the extension's Save page).
- Update the libraries:
cd extension/lib curl -sSLO https://unpkg.com/turndown/dist/turndown.js curl -sSLO https://unpkg.com/turndown-plugin-gfm/dist/turndown-plugin-gfm.js curl -sSL https://unpkg.com/@mozilla/readability/Readability.js -o Readability.js - Tweak the icon: edit
generate_icons.py, thenpython3 generate_icons.py. - iOS too: drop
--macos-onlyfrombuild.sh. - Change the bundle ID / app name: edit the flags in
build.sh.
Released under the MIT License.
Bundled third-party code in extension/lib/:
Turndown (MIT),
turndown-plugin-gfm (MIT),
Readability (Apache-2.0).