Hotlink Media

by semsevens
5
4
3
2
1
Score: 50/100
New Plugin

Description

Play hotlink-protected videos, audio and images in Obsidian notes by fetching them with the headers the source site expects.

Reviews

No reviews yet.

Stats

0
stars
downloads
0
forks
0
days
0
days
0
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
4
commits

README file from

Github

CI

Play hotlink-protected videos, audio and images in your notes.

The problem

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.

What this plugin does

For each <video>, <audio>, <img> or <source> in a rendered note whose URL matches one of its rules, it:

  1. Takes over the element: moves the URL aside so Obsidian doesn't request it and fail.
  2. Fetches the file itself when the element scrolls near the viewport, sending the headers the source site expects.
  3. Hands the file to the element as a blob: URL. Nothing is written to your vault; the file lives in memory until the note is closed.
  4. If a site's rule knows how, gets a fresh URL when the old one is rejected and retries.
  5. If it still fails, shows a short note under the media with a link to the original page.

URLs that match no rule are never touched. Your markdown is never modified.

Works in Reading view and Live Preview.

Supported sites

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.

Network use

This plugin makes network requests, and only for media that match a rule:

  • The media file itself, from the media's own host (for WeChat: mpvideo.qpic.cn), with the headers listed in the rule.
  • The original article page, only when the media URL was rejected and the rule can refresh it (for WeChat: the 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.

Adding a site

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
}

Notes

  • A file is downloaded in full before it plays, so long videos take a few seconds to start.
  • The same file shown in both Reading view and Live Preview is downloaded once.
  • Files are fetched only when they scroll within 400px of the viewport, so a note with many videos does not download them all on open.

Development

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/.

License

MIT