IDAP BLOG App Development

How to Protect Paid Content

Who will benefit from the article

The article will be useful for developers who want to protect website content from thieves and hackers. We’ll discuss the examples of unsafe data storing, as well as the ways to protect data leaving the business untouched. 

General info

Nowadays, tons of online resources specialize in the distribution of all kinds of original content, and all of them are concerned about data protection. In our post, we’ll focus on the video content as an example of what needs to be protected, namely:

  • learning materials;
  • lectures;
  • concerts;
  • movies;
  • TV shows.

Every website has its own rules and prices (if any) for content distribution, for example:

  • all videos are available for free in SD quality, high-quality is available only after purchase or paid subscription;
  • videos are available to watch only in a short period of time;
  • the videos are edited into short clips that can be viewed as a preview or as a GIF. The full versions are available for purchase or after subscription.  

Steps to protect paid content

Data filtering

First of all, you have to make sure that no extra data is sent from the server side to the client side, namely:

  • direct links to paid videos in .mp4 format;
  • direct links to playlists in m3u8 format;
  • any links to paid video content.

Whether the data is sent via ajax or gets recorded in html right away, there’s no need to send it to the client side if the user does not have corresponding rights. Modern web browsers allow us to see what data was sent to the server and what was received from there as well, filter it through, and even find the direct link to the desired content. If there’s trouble filtering the data due to its large amount, then you need to go for a permission check step.

URL validation

At this stage, you need to explore all the URLs that are somehow associated with the URL for the paid content. The table below describes examples of how one can get access to a paid video from the free link.

URL validation

The table demonstrates the simplest examples. In reality, unauthorized ways of getting to paid content differ from one website to another. The one common thing here is a web developer’s mistake in a logical connection between free and paid content that gives users a chance to sneak paid content without permission. To defend the exclusive data, you need to change the method links are formed in, namely — each link has to have different hashes in its URL, for example:

  • example-site/videos/icodTEXrHi4ZY089Xbj9knLGg237pOEi/1080.mp4
  • example-site/videos/icodTEXrHi4ZY089Xbj9knLGg237pOEi/Z3kWRLttS6wZM75m1vwsDl2a64cUBMbF.mp4
  • example-site/videos/icodTEXrHi4ZY089Xbj9knLGg237pOEi/Z3kWRLttS6wZM75m1vwsDl2a64cUBMbF.mp4?param=OseCuTZDgIfD5hEv4o0xLgzTZcLhfDR2

Generally speaking, the more unique hashes, the better. But also, do not forget to encode them well so that there’s no way back. For example, if you encode any number in md5, then it can be easily decrypted, so either you always have to add any word to id or generate a random string. When generating random strings in hashes, you have to use:

  • small latin letters;
  • capital latin letters;
  • numbers;
  • restriction of the minimum length to 16 characters.

It is also necessary to avoid the same url encoding algorithms for different kinds of media. Meaning, you should use one algorithm to generate images and another one for videos. That way, it will be more difficult for an attacker to find the logic in URLs. And finally, avoid sending hashes, or the data hidden there, to the client side.

Permission check 

This is the most important stage which is basically a verification process of the rights to access certain content. This means, every piece of paid content has to be checked by server for the corresponding permissions. For example, if a file by URL example-site/videos/full/video_name.mp4 should be accessible only to the person who bought it, then you can position nginx to send the requests to example-site/videos/get-full-video/video_name address.The get-full-video here would be the server endpoint where you need to implement the following:

  • user permissions check;
  • requested file availability;
  • file reading;
  • response sending.
Client-server interaction scheme

Client-server interaction step by step:

  1. The client directly requests the file.
  2. Nginx blocks direct access and redirects the request to the server.
  3. Server checks for permissions.
  4. In case of insufficient permission, the server sends back an error with the 403 Forbidden status.
  5. If the permission check goes successfully, then the server reaches for the file in storage.
  6. The server sends the file to the client.

General recommendations

If you use the m3u8 playlists format for video files and block access to the file for everyone who lacks permission, then you also have to check the access to the files that are described there as well. Usually, these belong to the ts type. Oftentimes, developers miss the issue when the main file is locked for access, but it is possible to assemble it in pieces from ts files.

If the website allows users to watch a shortened clip instead of a full video, then you should never share the access to the full file and try to block viewing after a certain time. In that case, a user can easily download the file following that direct link. Instead, we recommend cutting out the pictures or creating a separate video preview.


In order to protect the access to paid content, it is enough to use all three levels of protection, but do not forget that paid content can still be downloaded or recorded using screen recording. To prohibit downloading files, you need to look for special utilities to block data downloads, and a watermark with a website address can help to prevent screen downloads, as an additional attraction for customers, but you also need to add copyright to protect data at the legal level so that you can file a complaint if such the same content will be found on another resource.

(6 votes, average: 5.00 out of 5)