Leadership

How to Stop Users to download the videos on your site

A friend asked me how to prevent users from downloading videos off his site. I gave him the honest answer first.

15 Oct 2023

How to Stop Users to download the videos on your site

A friend asked me how to prevent users from downloading videos off his site. I gave him the honest answer first.

You can't. Not fully. Not technically.

Someone can always full-screen your video and screen-record it. That is not a download from your servers, and there is nothing you can do about it.

But most users won't go that far. So the real question is: how do you make it hard enough that casual users don't bother, and how much protection does your content actually justify?

Think of it as layers, from cheap deterrents to real cryptographic protection. Here is each one, and how much it actually buys you.

Disable right click

Strip the context menu from your video element. It removes the easy "Save video as..." option:

Typescript
const video = document.getElementById("player") as HTMLVideoElement;
video.addEventListener("contextmenu", (event) => {
  event.preventDefault();
});

Be honest about what this is: a speed bump. It stops the least curious user and no one else. Do it, but do not believe it protects anything.

Remove the download and picture-in-picture controls

The native video controls include a download button in most browsers. Turn it off, along with the other escape hatches:

Html
<video
  id="player"
  src="/media/lesson-01.mp4"
  controls
  controlsList="nodownload noplaybackrate"
  disablePictureInPicture
></video>

controlsList="nodownload" hides the download button and disablePictureInPicture stops the pop-out player. Still cosmetic, but it closes the obvious one-click routes.

Stop shipping the raw file URL

This is the one that actually matters at the cheap end. If your page contains <video src="/media/lesson-01.mp4">, none of the above matters: anyone opens the browser network tab, sees the .mp4, and downloads it directly. The controls are irrelevant because they never touch the file URL.

Two things follow from this:

  • Never expose a stable, public, direct link to the source file.
  • Serve the media through a path you control and can authorize per request.

That leads to the techniques that do real work.

Stream in segments with HLS or DASH

Instead of serving one big .mp4, serve the video as a playlist of small chunks using HLS (.m3u8 plus .ts or .m4s segments) or DASH. There is no single file to "Save as", only dozens of fragments described by a manifest.

Typescript
import Hls from "hls.js";

const video = document.getElementById("player") as HTMLVideoElement;
if (Hls.isSupported()) {
  const hls = new Hls();
  hls.loadSource("/media/lesson-01/index.m3u8");
  hls.attachMedia(video);
}

A determined user can still script the segments back together, but you have moved from "right click, save" to "write a downloader", which filters out almost everyone. HLS is also better for playback: adaptive bitrate, faster start, less buffering.

Sign your URLs and expire them fast

Segmented delivery only helps if the segment URLs are not permanent public links. Put the media behind a CDN that supports signed URLs or signed cookies (CloudFront, Cloudflare, Bunny) and hand the player a token that expires in minutes:

Typescript
import { getSignedUrl } from "@aws-sdk/cloudfront-signer";

const url = getSignedUrl({
  url: "https://cdn.example.com/media/lesson-01/index.m3u8",
  keyPairId: process.env.CF_KEY_PAIR_ID!,
  privateKey: process.env.CF_PRIVATE_KEY!,
  dateLessThan: new Date(Date.now() + 60_000).toISOString(),
});

Now a copied link is dead within a minute, and you can require the user to be authenticated before you mint one. This is the point where casual sharing stops working.

Check who is asking

Alongside signed URLs, gate the manifest and segments behind your own auth. Require a session, verify it on every segment request, and rate-limit. You can also check the Referer and Origin headers to block hotlinking from other sites, though treat those as a weak signal since they are easy to spoof. Auth tokens are the real control, headers are a bonus.

Watermark to deter redistribution

If the threat is a paying user re-uploading your course elsewhere, make the leak traceable. Burn a visible watermark with the viewer's email or account id into the player overlay, or use forensic watermarking that embeds an invisible per-user marker in the stream. It does not stop the copy, it makes the copier accountable, which changes behavior.

DRM: the only thing that actually stops downloading

Everything above raises the cost. DRM is the only approach that cryptographically prevents it. With Widevine (Chrome, Android), FairPlay (Safari, iOS), and PlayReady (Edge), the video is encrypted and the browser's Encrypted Media Extensions hand decryption to a secure module that never exposes the decrypted bytes to JavaScript. Playback requires a license from your license server, which you control.

This is what Netflix and every major streaming service uses. It is also heavyweight: you need a packaging pipeline, a multi-DRM license service (often through a provider like Axinom or EZDRM), and a player such as Shaka Player. Reach for it only when the content genuinely justifies the cost and complexity.

So what should you actually do?

Match the effort to the value of the content:

  • Hobby or marketing videos: nodownload, no raw file URL, and HLS. Done. Do not overthink it.
  • Paid courses: authenticated, signed, short-lived HLS URLs plus a visible per-user watermark. This stops casual sharing and makes leaks traceable without a DRM budget.
  • High-value or licensed content: full DRM with Widevine, FairPlay, and PlayReady. Nothing less actually prevents capture.

Wrapping up

You cannot make video truly undownloadable, screen recording alone guarantees that. What you can do is stack deterrents so that copying costs more effort than it is worth to your audience. Start by never exposing the raw file, serve segmented streams over signed and authenticated URLs, watermark when redistribution is the risk, and escalate to DRM only when the content demands it. Pick the layer that fits the value, and stop paying for protection you do not need.

Go further
Live cohort on Maven

From Senior to Staff: Master the Architecture Skills That Get You Promoted

Go from shaky in design reviews to the engineer everyone trusts to architect the hard stuff.

View the live cohort

Keep reading