Choosing a defense
Compare the built-in defenses, pick one for your setting, and see what an anonymity set adds beyond a single video.
Just want to use Dodge? See install. New to video fingerprinting? Start with learn.
A defense is an extended manifest: a standard DASH MPD paired with per-representation download schedules describing the target network traffic pattern. Download schedules are built from cycles, Dodge's generalized download unit, which replace segment downloads. The extended manifest format page is the authoritative reference for cycle syntax.
This page covers what each built-in defense does, which one to use, and how anonymity sets extend protection beyond a single video. For writing a new defense, or generating and distributing defenses at scale, see defense development.
Built-in defense strategies
Three defenses are included in the generator library today. Each carries a category badge naming what it does to segment sizes: a regularization defense shapes a specific traffic pattern, a randomization defense introduces random noise, and a diagnostic defense doesn't change the traffic pattern at all and exists for testing.
baseline Baseline (passthrough) Mirrors the undefended DASH download pattern: one cycle per segment.
selected_representations-
Comma-separated representation keys ('0:v0') to include; a bare id ('v0') selects that representation in every period, and blank means every representation.
constant-size Constant-size defense Replaces every segment download with num_cycles cycles of cycle_size each, and can append trailing padding blocks to hide video duration.
selected_representations-
Comma-separated representation keys ('0:v0') to include; a bare id ('v0') selects that representation in every period, and blank means every representation.
cycle_size-
Bytes per cycle. Required. The per-segment byte total is cycle_size × num_cycles, which must cover the largest measured segment in the representation, and cycle_size itself must be no larger than the smallest, since a cycle cannot fetch more bytes than the segment holds. Generation fails and reports workable values if either bound is missed.
num_cycles-
Number of data cycles per segment. A representation whose segments vary widely in size needs enough of them that a cycle size small enough for the smallest segment still covers the largest.
init_size-
Bytes per init cycle. Required. Every init cycle is exactly this size, and the value is deliberately not per-representation, so initialization traffic looks the same whichever representation it belongs to. init_size × init_cycles must cover the largest initialization segment among the defended representations, and init_size must be no larger than the smallest.
init_cycles-
Number of equal-size cycles used to fetch the initialization segment.
trailing_min_blocks / trailing_max_blocks-
Inclusive range for how many whole padding blocks, each a fake segment of num_cycles × cycle_size, are appended after the real segments to extend apparent duration. Default 0 / 0 disables trailing padding. Choose a value that matches your anonymity set.
seed-
Optional seed for the trailing padding count; blank draws randomness from the OS.
random-padding Random padding Splits each segment into cycles of a chosen size, then appends a random number of padding cycles of the same size. Can also append trailing padding blocks to hide video duration. Cheaper than constant-size, but offers less protection.
selected_representations-
Comma-separated representation keys ('0:v0') to include; a bare id ('v0') selects that representation in every period, and blank means every representation.
cycle_size-
Bytes per cycle. Required. Segments are split into ceil(size / cycle_size) data cycles of this size, and padding cycles are the same size. cycle_size must be no larger than the smallest segment in the representation, since a cycle cannot fetch more bytes than the segment holds.
init_size-
Bytes per init cycle. Required. Every init cycle is exactly this size, and the value is deliberately not per-representation, so initialization traffic looks the same whichever representation it belongs to. init_size × init_cycles must cover the largest initialization segment among the defended representations, and init_size must be no larger than the smallest.
init_cycles-
Number of equal-size cycles used to fetch the initialization segment.
min_extra / max_extra-
Inclusive range for how many padding cycles are appended after each segment.
trailing_min_blocks / trailing_max_blocks-
Inclusive range for how many trailing padding blocks are appended after the real segments to extend apparent duration. Default 0 / 0 disables trailing padding. Choose a value that matches your implicit/explicit anonymity set.
trailing_min_cycles / trailing_max_cycles-
Inclusive range for how many identical cycles fill each trailing padding block, so trailing blocks vary in length like real segments do.
seed-
Optional seed for the padding count; blank draws randomness from the OS.
baseline is a diagnostic defense: it emits one full cycle per segment, using the Dodge pipeline without changing payload sizes. It exists for testing purposes but does not provide any protection, so it should not be used for privacy.
constant-size and random-padding have not been evaluated yet (they will be soon, and results will be published here), but we expect both to provide some degree of protection. In particular, constant-size should provide significant protection as long as suitable parameters are chosen; see below for details. Both can also append trailing padding, extra padding blocks downloaded after all real segments, to extend the video's apparent duration.
These defenses require measurements (HTTP HEAD requests) to determine segment sizes for the byte ranges. Those probes are size-padded, and they are accompanied by padding probes, so the HEAD requests don't fingerprint the stream or give away its duration. The generator page explains how this is done safely.
Which one to use
For a single video, the guidance is short. No video is ever really defended in isolation, though; anonymity sets below cover why.
baselineis never a privacy defense. Use it to verify that a stream plays in Dodge.random-paddingis the lower-overhead option: every cycle on the wire is the samecycle_size, so real and padding cycles are indistinguishable and the exact segment size is hidden to at leastcycle_sizegranularity. The number of cycles still scales with the real size to some extent, since a big segment still needs more cycles.constant-sizeremoves the per-segment size signal entirely: every defended segment occupies the same number of bytes on the wire. It's the strongest built-in defense for a single video and the default when a defense is generated automatically, at the highest bandwidth overhead of the three.
The latter two defenses require segment measurements to generate; the web generator's measure step is not optional for them.
None of these hides everything. Trailing padding extends a session's apparent duration by a random amount, hiding its exact length, but a defended session is still recognizable as some defended session with a certain length and rate. A defense generated for a single video also cannot make that video look like any other; that requires an anonymity set. For what a defense leaves exposed regardless of which you pick, see threat model & security.
Anonymity sets
The strongest defenses are built for groups of videos rather than single videos. An anonymity set is a group of videos whose defended traffic is mutually indistinguishable: every member produces the same sequence of wire sizes, so an observer who recognizes the pattern learns only that the viewer is watching one of the videos in the set, not which one. The paper's proof-of-concept defense, Dodge-mimic, works this way: it groups a catalog's videos into sets and shapes each member to its set's common pattern.
Dodge-mimic builds its sets by coordinating across a catalog. Someone defending many videos at once, such as a content provider or the maintainer of a defense repository, shapes the videos simultaneously and publishes the extended manifests together. Grouping videos with similar durations and qualities keeps the common pattern as cheap in bandwidth as possible. A single per-video generation run can't do this sort of coordination on its own.
You don't necessarily need a mimicry algorithm to get an anonymity set, though. The constant-size defense pads every segment to the same fixed size, num_cycles × cycle_size bytes, no matter what the video is. So two videos generated with the same num_cycles and cycle_size (and padded to the same duration with trailing padding) produce byte-for-byte identical traffic. Any video whose largest segment fits within num_cycles × cycle_size, and whose smallest segment is at least cycle_size, can be padded to that target, which makes a constant-size set arbitrarily extensible: you can keep adding videos one generation run at a time, without regenerating the ones already in the set. Doing this through the web generator is tedious, though, since you generate each video separately and have to pin the same parameters every time. But it's a real way to build an anonymity set with no central mimicry pass.
Because everything is padded to one universal size rather than a per-set negotiated one, constant-size sets tend to be large and uniform, where a mimicry set is small and tuned to its members. That uniformity costs bandwidth, usually much more than Dodge-mimic. But it's also what makes the set hard to pick apart: the more videos share exactly one pattern, the less any single observation reveals, and the harder it is to chip away at the set.
Chipping away is the thing to worry about, because an anonymity set only hides which video within the set you're watching. It does nothing about what the adversary already knows from outside the traffic. If they can see which page you're on (perhaps via website fingerprinting), or which provider or category you're browsing, that narrows the candidates before a single byte is analyzed. A few more things can shrink a set or break it outright:
- If some videos in the set are available at a quality the others aren't, playing at that quality falls outside the shared pattern and breaks the set. That's one reason to strip revealing adaptation sets out of an MPD before shaping it, rather than embedding it as-is.
- Providers often publish view counts, likes, and similar figures, and those hand the adversary base rates for re-ranking the candidates within a set. A rarely watched video and a viral one aren't equally likely to begin with, even when their traffic is identical.
- The label on the set can leak information too. When every video shares a category or content type, or the set was built by grouping similar durations (so short clips end up together, away from long videos), membership in the set is itself informative.
- Time helps the observer as well. Someone who sees you across several videos or sessions can intersect the candidate sets from each, and a viewer who keeps reappearing in overlapping sets is pinned down faster than any one session would suggest. That's another reason a large, dissimilar set beats a small, tightly grouped one.
A big constant-size set (many unrelated videos padded to one identical pattern) mitigates most of these threats better than a small set grouped by similarity does. That's why we expect uniform, extensible sets to hold up well despite their overhead. This is not automatic, though. Building and hardening a set takes deliberate parameter choices and MPD cleanup (dropping adaptation sets that expose extra qualities, stripping ad-break periods) and then someone still has to vet the result. That's why defense repositories exist as a distribution channel: to publish sets that were built and checked purposefully, rather than assembled haphazardly.
See also
- Threat model & security: what a defense doesn't hide, regardless of which you pick.
- Defense development: writing and generating defenses, and distributing via repositories.
- Defense generator: produce an extended manifest from an MPD in your browser.
- Extended manifest format: the reference for extended manifest syntax.