跪拜 Guibai
← Back to the summary

Every Front-End Anti-Copy Trick, Ranked by How Fast It Breaks

Let me tell you the conclusion first: you can't prevent it, you can only make it harder

Front-end cannot stop copying; all it can do is make the act of copying more troublesome. How troublesome depends on how much user experience you are willing to sacrifice and how badly the other party wants your content.

I turned all the anti-copy methods I could find on the market into an experimental page. Each technique is a switch that you can turn on with your own hands and then bypass with your own hands:

Anti-Copy Lab

Below, I will explain these methods from weakest to strongest, each covering how to write it, who it can stop, and how to break it.


First, understand one thing: if it can be seen, it can be taken

Here lies the fundamental dilemma of anti-copy.

The browser must render content into pixels on the screen for the user to see it. If the user can see it, they can screenshot it; if they can screenshot it, OCR can turn it into text. You cannot block this path unless you prevent the user from seeing the content at all—which defeats the purpose of anti-copy.

So, front-end anti-copy has never been about solving "whether it can be taken"; that question was answered long ago. It's about "how much effort it takes to get it." Once you understand this, you'll know how to evaluate all the techniques below.


Tier 1: CSS for the honest

user-select: none

The most common trick. One line of CSS to prevent users from selecting text:

.protected {
  user-select: none;
  -webkit-user-select: none;
}

If it can't be selected, naturally Ctrl+C won't work.

How to break it? Open F12, delete this rule in the Elements panel, or type this in the Console:

document.querySelector('.protected').style.userSelect = 'text';

Selection is restored in three seconds.

Disabling the right-click menu

document.addEventListener('contextmenu', e => e.preventDefault());

The user cannot bring up the "Copy" menu via right-click. The side effect of this trick is greater than its effect—users who want to use right-click to translate or look up words are all blocked, and the experience is immediately off-putting.

Breaking it is even simpler: there is a switch in the browser settings that says "Allow websites to block right-click"; just turn it off.

The common feature of these two tricks: they stop people who know nothing about technology, but anyone who knows a little can break them on the spot. In my lab, I gave both a "bypass difficulty" of 1, meaning a novice can handle it in ten seconds.


Tier 2: JavaScript blocking events

Intercepting the copy event

document.addEventListener('copy', e => {
  e.preventDefault();
});

When the user presses Ctrl+C, the copy operation is cancelled, and nothing goes to the clipboard.

Slightly harder to break than the CSS trick, but only slightly. Register a listener in the capture phase in the Console first to intercept the event:

document.addEventListener('copy', e => e.stopImmediatePropagation(), true);

Transparent overlay layer

Place a transparent div on top of the text. The user's mouse clicks on the overlay and cannot select the text underneath:

.overlay {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  z-index: 999;
}

The bypass method is the same as before: F12 to delete the overlay element, or set its pointer-events to none.


Tier 3: A different approach—allow copying but add something extra

The biggest problem with the hard-blocking tricks above is that they hurt normal users. Someone just wants to quote a sentence from you, only to find they can't even select it—a terrible experience.

So mainstream websites changed their approach: don't block copying, but secretly add something to the copied content.

Clipboard content replacement

document.addEventListener('copy', e => {
  e.preventDefault();
  const text = window.getSelection().toString();
  e.clipboardData.setData('text/plain',
    text + '\n\n——Source: xxx, reproduction prohibited');
});

You copy a paragraph, paste it, and find an extra line with a source statement and original link appended.

Zhihu, CSDN, and The New York Times all use this set. Its cleverness lies in this: it doesn't affect normal reading and quoting, but when the content is taken away, the source can be left behind. Shifting from "prohibit copying" to "copy if you want, but bring my attribution" is actually more valuable for the content owner.

This trick can also be broken—select the text in DevTools, right-click "Store as global variable" to directly get the raw DOM text, bypassing the copy event. But for the vast majority of republishers, that line of source statement has already achieved its purpose.


Tier 4: Make the content not "text" at all

At this tier, the thinking changes: since text in the DOM can be extracted, don't let the content exist in text form.

Canvas rendering

Use fillText to draw text onto a Canvas:

const ctx = canvas.getContext('2d');
ctx.font = '16px sans-serif';
ctx.fillText('Confidential content', 10, 30);

What the user sees is an image. There are no text nodes in the DOM, and a regular crawler will scrape a blank.

The cost is huge: content cannot be indexed by search engines (SEO goes to zero), screen readers cannot read it (accessibility collapses), and rendering performance is poor. Baidu Wenku's paid document preview takes this path.

The bypass: screenshot plus OCR, or directly hook Canvas's fillText call to get the parameters.

Font mapping obfuscation

This is the strongest trick the front-end can pull off. Customize a font file and shuffle the character encoding mapping—what the code writes is one set of encodings, what the font displays is another set of characters.

@font-face {
  font-family: "Obfuscated";
  src: url("shuffled.woff2");
}
/* The HTML writes "xk#2m", but the screen displays "hello" */

The page looks like normal text, but what you copy down is garbled characters like xk#2m, because the clipboard gets the real encoding, not the glyphs rendered by the font.

Qidian's paid chapters use this trick, and the font mapping might even be different for each user and each chapter.

The bypass: analyze the font file's cmap table to reverse-engineer the mapping relationship, or the old method—OCR. In the lab, I gave it a bypass difficulty of 5, meaning it requires specialized tools and techniques, but it's still not impossible.


I turned these tricks into an attack-defense simulation

Just saying "it can be broken" is too abstract, so I added an attack-defense simulation in the lab:

Anti-Copy Lab - Attack-Defense Simulation

First, you pick a combination of protections on the test bench, then choose an attacker level—from "an average user who only knows Ctrl+C" to "a professional crawler with OCR and automation tools"—and see how long each line of defense holds.

The conclusion is very consistent:

This corresponds exactly to a simple truth: the real value of protection lies in raising the bypass cost to a point where the attacker feels it's not worth it. Absolute blocking was never possible. Dealing with a casual visitor copying text versus dealing with a crawler determined to scrape the site requires completely different protection intensities.

Note: The "bypass time" for each technique in the lab is a relative value simulated by a formula based on difficulty level and attacker level, used to visually compare strengths and weaknesses, not representing precise real-world seconds.


References

  1. MDN Web Docs, "user-select" CSS property https://developer.mozilla.org/en-US/docs/Web/CSS/user-select
  2. MDN Web Docs, "Element: copy event" https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event
  3. MDN Web Docs, "ClipboardEvent.clipboardData" https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
  4. W3C, "Clipboard API and events" https://www.w3.org/TR/clipboard-apis/
Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

王三岁_

Great article, thanks for sharing.