semsevens90 downloadsArchive remote URLs from markdown locally and serve from local cache on render.
Archive remote URLs referenced in your markdown to a local cache, and transparently serve the cache when the note is rendered. Defends your vault against link rot without rewriting any markdown.
Notes that quote articles, tweets, or research often embed remote images, video, or audio:


When the original host disappears (the WeChat account is deleted, the tweet is removed, the CDN expires the URL), every embed in your vault silently breaks. The note still reads, but the visual context is gone.
For every remote <img>, <video>, <audio> it encounters:
<dir>/_archive/<sha1-of-url>.<ext> (a sibling folder next to the markdown that referenced it).src to the local archive at display time — in both Reading mode and Live Preview..md never changes. If you later view the file outside Obsidian, share it, or this plugin is uninstalled, the remote URL still works as a fallback.The archive is content-addressed by URL hash, so the same URL appearing in multiple notes is stored once.
┌──────────────────────────┐
│  │ ← markdown stays as-is
└──────────┬───────────────┘
│
▼
┌──────────────────────────────────────┐
│ Scanner extracts URLs │
│ Policy decides which to archive │ ← domain rules + media extension
│ Downloader fetches with retry │
│ File saved at _archive/<sha1>.<ext> │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ At render time: │
│ resolve(url) → vault path → swap │ ← Reading + Live Preview
│ if local present, else leave remote │
└──────────────────────────────────────┘
The plugin archives in three ways:
Scan vault & archive remote resources walks every markdown file in scope.| Setting | Default | Purpose |
|---|---|---|
| Archive directory name | _archive |
Subfolder name (sibling to each .md) that holds cached files. |
| Auto-archive on file modify | on | If off, only the manual scan command triggers downloads. |
| Included paths | (empty = whole vault) | Newline-separated vault paths to operate on. Example: raw/wechat. |
Built-in rules in policies.ts:
| Domain | Action | Notes |
|---|---|---|
mmbiz.qpic.cn, res.wx.qq.com, mmbiz.qlogo.cn |
archive | WeChat — requires Referer: https://mp.weixin.qq.com/ |
pbs.twimg.com |
archive | Twitter / X images |
video.twimg.com |
skip | Twitter videos are large and the CDN is long-term stable |
youtube.com, youtu.be, vimeo.com |
skip | stream-only |
| (anything else) | archive only if URL has a media extension (.jpg/.png/.mp4/…) |
prevents accidentally fetching HTML page URLs |
[0, 1s, 3s] backoff.http:// URLs are automatically upgraded to https:// (Obsidian's requestUrl does not accept cleartext HTTP).<archive>/.failed.jsonl with URL, error, and timestamp.While awaiting Community Plugins approval:
BRAT: Add a beta plugin for testing.semsevens/obsidian-archive-redirect.Download main.js and manifest.json from the latest release into <vault>/.obsidian/plugins/archive-redirect/, then enable.
crypto module; mobile support requires swapping to Web Crypto (which is async) and is planned for a later release.src after Obsidian renders the element. It does not interfere with other plugins (e.g. auto-embed) that work on page URLs.MIT