semsevens19 downloadsPlay hotlink-protected videos, audio and images in notes by fetching them with the headers the source site expects.
Play hotlink-protected videos, audio and images in your notes.
Many sites only serve their media to requests that come from their own pages: the server checks the Referer header. In a browser, reading the original article, the Referer is the site itself, so the video plays. Put the same URL in an Obsidian note and the Referer becomes app://obsidian.md. The server answers HTTP 403 and you get a black box that never plays.
A typical case is a WeChat Official Account article (mp.weixin.qq.com) clipped into Obsidian: the note keeps the <video> tags, but every video is blocked.
Obsidian does not let plugins rewrite request headers globally, so the usual fix is not available.
For each <video>, <audio>, <img> or <source> in a rendered note whose URL matches one of its rules, it:
blob: URL. Nothing is written to your vault; the file lives in memory until the note is closed.URLs that match no rule are never touched. Your markdown is never modified.
Works in Reading view and Live Preview.
| Rule | Handles | How |
|---|---|---|
| WeChat Official Account videos | mpvideo.qpic.cn |
Sends Referer: https://mp.weixin.qq.com/ and a browser User-Agent. When rejected, re-fetches the original article (the note's source frontmatter field), finds the same video's fresh URL, and retries, up to 4 attempts. |
Measured on 2026-10-04: the same WeChat video URL works only part of the time (3 out of 8 checks over two hours, one every 15 minutes), while re-fetching the article always yields working URLs. That is why the rule refreshes and retries rather than giving up on the first 403.
This plugin makes network requests, and only for media that match a rule:
mpvideo.qpic.cn), with the headers listed in the rule.mp.weixin.qq.com URL in the note's source frontmatter field).No other requests are made. No data about you or your vault is sent anywhere. There is no telemetry.
Requests use Node's built-in http/https modules instead of fetch or requestUrl: browsers forbid setting Referer by hand, and Electron's network stack does not reliably send it either. That is why the plugin is desktop only.
Add an entry to RULES in src/rules.ts:
{
id: "example",
name: "Example images",
match: /^https:\/\/img\.example\.com\//, // which media URLs this rule handles
headers: { Referer: "https://www.example.com/" }, // headers to send
// refresh: optional, how to get a fresh URL when the old one is rejected
}
npm install
npm test # rules, retry and DOM takeover logic, including real WeChat article data in tests/fixtures/
npm run build # produces main.js
To install manually, copy main.js, manifest.json and styles.css into <vault>/.obsidian/plugins/hotlink-media/.
MIT