FeaturesSecurityPricingCompareDevelopersBlogStart Free
BlogAugust 4, 2026

Do watermarks survive screenshots?

A browser cannot block a screenshot, and no data room can claim otherwise. That leaves attribution as the only real control, so we measured it: 64 sampled 25% crops of a burned page, and how much of the participant's identity each one still carried.

Start with what is impossible

Screen capture happens in the operating system. A web page has no API that can see it, block it or be told it occurred. Disabling right-click, trapping PrintScreenand blanking the page on window blur are all defeated by a second device pointed at the monitor, and most are defeated by the browser's own reader mode. Any vendor selling screenshot prevention in a browser is selling a deterrent.

What remains is attribution. If a page reaches somewhere it should not, the question stops being whether it could have been copied and becomes whose session produced the copy. That question has a measurable answer, so it is the one worth testing.

  • CSS overlay drawn in the browserbypassable

    One element in the DOM. Delete it in developer tools and the clean page is underneath, because the clean page was already downloaded.

  • Canvas drawn from client statebypassable

    Still client-side. The unmarked source image was served, so it is already in the browser cache and reachable from the network panel.

  • Composited into the page image on the serverenforced

    The bytes that leave the server are already marked. There is no element to delete and no clean copy to reach.

Where a mark can live, and whether deleting one element removes it.

Method

Pages are rasterised at 150 DPI to 1240 by 1755 WebP images. The identity mark is composited onto the pixel buffer and only then encoded, so the encoded bytes are what any bypass retrieves. The mark is tiled at a 30 degree rotation with a half-pitch stagger on alternate rows, and each glyph gets a one-pixel halo in the opposite luminance direction so it stays readable over both dark text and white paper. The room can set opacity, but the burner clamps it up to a floor of 25, so a room configured to 1 renders byte-identical to a room configured to 25.

The test itself:

  1. Render a synthetic memo page at the exact geometry the rasteriser emits, WebP quality 85.
  2. Pipe it through the production burner with a four-line identity: name, email, IP address, UTC timestamp.
  3. Take the per-pixel absolute difference between the marked and clean images. That difference is the watermark, since the two share a source and an encoder.
  4. Sweep 64 crop windows on an 8 by 8 grid, each 25% of the page width and 25% of its height, 310 by 438 pixels. Score each window as the fraction of pixels differing by more than 12 levels.
  5. Repeat the sweep after JPEG quality 50, after a 50% downscale, and after both.

The 64 windows exist so the reported number is not the average case. An attacker crops where the mark is thinnest, so the figure that matters is the minimum across all 64, not the mean.

One control first. Encoding the clean page through WebP quality 85 a second time, with no burn at all, produces a maximum window score of 0.0022%. Re-encoding noise is three orders of magnitude below the signal, so what the sweep measures is the mark.

Reproducing it

The burner is infrastructure/hetzner/worker/src/watermark.py and it is a command-line program that reads an image on standard input. It needs Python 3 and Pillow.

python3 watermark.py --text "Sara Al-Otaibi
sara@example.com
IP 203.0.113.42
2026-08-04 09:14 UTC" \
  --position tiled --opacity 15 --color gray \
  --min-crop 0.25 --quality 85 < page.webp > marked.webp

The full sweep, including the assertions that a blank identity is refused and that two participants receive different bytes, lives in tests/rasterization/watermark-burn.test.ts.

Results

11.6%
Ink in the leanest of 64 crops
8×8 sweep, 25% windows, 4 Aug 2026
15.0%
Mean ink across the 64 crops
Same run
0.0022%
Ink from re-encoding alone
Control: WebP q85, no burn
Watermark ink retained in a 25% crop, before and after re-compression. Minimum is the worst of the 64 sampled windows.
CriterionMinimumMeanMaximum
No further processing11.6%15.0%18.6%
JPEG quality 5013.4%16.9%19.8%
50% downscale11.8%15.3%19.8%
JPEG q50 then 50% downscale11.7%15.2%20.0%
Watermark ink retained in a 25% crop, before and after re-compression. Minimum is the worst of the 64 sampled windows.

JPEG quality 50 raises the score rather than lowering it, because lossy compression spreads each glyph edge across neighbouring pixels and more pixels end up differing from the clean reference. That is an artefact of the measure, not extra durability. The number to read is the downscale row, where the mark loses half its resolution and still holds.

A 310 by 438 pixel crop of a watermarked document page. Diagonal grey text repeats across the crop showing the name Sara Al-Otaibi, the email sara@example.com, an IP address and a UTC timestamp, over the body line about revenue growth.
The leanest of the 64 windows, cropped at x=132 y=564. Name, email, IP and timestamp are all legible in fragments. The identity is a fixture, not a real participant.
A high-contrast difference map of the whole page showing the tiled watermark repeating diagonally, with the underlying body text visible only as very faint ghosting.
Marked page minus clean page, contrast lifted six times. Everything visible here is in the served bytes. Deleting elements in developer tools cannot reach any of it.
The same crop after JPEG compression at quality 50 and a 50 percent downscale, 155 by 219 pixels, with the diagonal watermark still present but faint.
The same window after JPEG q50 and a 50% downscale. The measured ink holds at 11.7%, though at this scale reading the fields by eye needs a contrast lift like the one above.

Two viewers, two files

Because the mark is composited per request, two participants opening the same page receive different bytes. That is what makes the mark evidence rather than decoration: a leaked image can be matched back to one session. If the burn fails for any reason, the page proxy returns 503 and never falls back to the clean image, and a blank identity string is refused outright rather than producing an unattributable page.

The watermark is one half of the answer. The other half is the audit trail, which records which participant opened which page and when, so a marked image found in the wild has a matching log entry to confirm it against.

Related: Where a permission filter has to live · How we test our own data room · The spreadsheet fidelity test · Pricing

Watermarking is on every paid tier. See what each tier includes.

FAQ

Questions about watermarks and screenshots.

No. A web page runs inside the browser, and the screen capture happens in the operating system, outside anything the page can reach. No JavaScript API can block it, and a phone camera pointed at the monitor defeats every software control anyway. Any vendor claiming screenshot prevention in a browser is describing a deterrent, not a control.
Attribution, not prevention. If a page leaks, the watermark tells you which participant's session produced the copy. That converts an anonymous leak into a named one, which is the difference between an unresolvable incident and a conversation with one person.
A CSS overlay can, in one click. A burned watermark cannot, because it is composited into the page image on the server before the image is encoded. The bytes that leave the server already carry the mark, so there is no element in the DOM to delete.
In our test, yes. The mark is tiled across the page, so a crop keeps whole tiles. Across 64 crop windows of 25% of each edge, the leanest window retained 11.6% watermark ink, and it held at 11.7% after JPEG quality 50 and a 50% downscale. Inpainting and multi-copy averaging attacks were not tested.
Start Free