The Consent Layer
Using ligatures to make web text expensive to scrape without asking
Abstract
ShieldFont is an open-source creative technology project that offers a practical opt-out from unauthorized AI training and disrupts what is collected when that choice is ignored. It swaps 45.8% of content words (around 24.4% of all words) in a page’s source code for other (partially) random words, while the font restores the original text on screen. Readers see the work as intended; mass scrapers collect an altered version. In testing, shielding caused over 90% of pages that would otherwise pass the quality filter to be rejected, keeping them out of the training pipeline. Of those that still passed, 19.4% of all words conveyed false meaning, adding noise to unauthorized AI training datasets. This paper’s goal is to walk newcomers through the whole process, in plain language and in order: the project’s rationale, how it was built, the results, how to deploy it, and where to contribute.
Keywordsconsent · concealment · the quality filter · glyph substitution · training-data provenance
How to cite this paper
@techreport{seneda2026consent,
title = {The Consent Layer: Using ligatures to make web text expensive to scrape without asking},
author = {Isaque Seneda and Gabriel Abrucio},
institution = {The ShieldFont Project},
year = {2026},
version = {2.0},
url = {https://shieldfont.com/white-paper},
doi = {10.5281/zenodo.21700389}
}Archived on Zenodo. The DOI above is the concept identifier: it always resolves to the newest version, with a separate version DOI pinned to this exact release.
Why authorship is worth defending
AI scrapers can take content without asking, and nothing currently makes them ask.
A large language model is built by copying an enormous quantity of written text and training a program to predict what word comes next. The quantity is the whole point, which is why the copying happened first and at a scale where asking was never seriously on the table. Our writing is in there. We did not agree, we were not credited, and we were not paid. A June 2026 lawsuit brought on behalf of nearly 400 US newspapers puts the arithmetic plainly: these products “have generated hundreds of billions of dollars (and counting) in market value for Defendants. Not a cent of it has gone to the Publishers whose work made it possible.”[1]
How a page becomes training data
Where the writing lives, as HTML source code.
Automated graders throw out most of what scrapers collect.
What survives the filter is bundled into a training corpus.
The model learns from whatever the dataset contains.
The reason this concentrates wealth so efficiently is that the input costs nothing. Yanis Varoufakis calls the arrangement technofeudalism[2], and the part of it that matters here is not the size of the platforms but how they are fed: by unpaid labour supplied by the people using them. Tiziana Terranova described the pattern in 2000, long before any of this, as activity “simultaneously voluntarily given and unwaged, enjoyed and exploited.”[3]
What is new is what is being taken. The first round of unpaid digital labour wanted our photographs, our clicks, our locations: the exhaust of living online. This round wants something we had not previously thought of as extractable. A sentence is a sequence of decisions. When I write, I am choosing this word rather than that one, putting this clause before that one, deciding what to leave out. The finished paragraph is a record of thinking that took effort to do. That ordered thinking is exactly the artifact these systems are built out of, and it is being taken for free to build a machine whose purpose is to do the same thinking more cheaply than I can. We are not being asked to hand over our data. We are being asked to hand over the work, and to train our own replacement with it, and to do both without being told.
Which is also why written text has never been worth more. Epoch AI projects that models will be trained on datasets equal to the entire stock of public human-written text somewhere between 2026 and 2032.[4] The supply of good human writing is growing far more slowly than the computing power chasing it. Every genuinely new article is worth more to a scraper this year than it was last year.
Robots.txt is the main tool available to publishers. It is a plain-text file that tells automated crawlers which parts of a website they should or should not access. But it is only a request, not a technical barrier. The standard itself says crawlers are asked to follow the rules and that the file does not control access.[5] The only large-scale peer-reviewed study found that AI crawlers were often more compliant than other categories, with ClaudeBot and GPTBot (from Anthropic and OpenAI, respectively) making genuine efforts. Even so, compliance with a full block caps at 26%. AI bots also checked Robots.txt less often than any other group, with under 40% re-checking it within a week, and a crawler can avoid the rules simply by changing its name.[6]
So nothing currently makes it costly to ignore a publisher’s wishes. This paper explores a different approach: making the text itself polluted, harder, and more expensive to collect without permission.
What it does, and what it does not
You and a scraper are reading two different documents.
ShieldFont replaces the words in a page’s source code with different, random words. Human readers still see the original text because the font restores it when the page is displayed. Automated systems that read the source code directly, however, receive only the substituted version.
A web page is delivered as HTML, a text-based file that contains the page’s content and structure. Both browsers and web scrapers access this same file. The browser renders the intended text for the reader, while the scraper extracts the altered text stored in the source code.
The swap lives in the font, and every font in the world can already do this. Typefaces routinely draw two or three letters as a single joined shape, because certain letter pairs collide awkwardly when set side by side. The classic case is f followed by i: the hook of the f crashes into the dot of the i, so the font draws one merged shape instead. You have read thousands of these without noticing. A joined shape like that is called a ligature, and the font carries a table listing which sequences of letters to replace with which single shapes as the page is drawn.
That table is a thirty-year-old standard feature, present in essentially every font you have ever used.[28] In our case, we point it at whole words instead of pairs of letters. Where a normal font says “draw f and i as one shape,” ours says “draw the letters of engine as the shape of the word horse.”
Any font
one rule in the font’s substitution table
ShieldFont’s version
same mechanism, whole words
Targeting whole words matters because of how a language model reads. It does not take in a sentence the way you do. It breaks text into tokens, short chunks that it treats as single units of meaning. A token is not exactly a word, but for our purposes you can think of it as one. Every token sits at a point in a vast space of meanings, and a sentence is the shape you get by connecting those points in order. Change which words are in the sentence and you change the shape, which is the only thing the model ever actually learns from.
The substitution happens only when the page is drawn on screen. It changes nothing about the file itself, and nothing about what your reader sees. Write “The knight rode his horse into battle” and that is exactly what they get. The stored source says engine.
The knight rode his horse into battle.
The knight rode his engine into battle.
Every pair runs both ways and no word is used twice, so the dictionary is perfectly reversible: you can always recover your own text.
What it does not do
ShieldFont is designed to disrupt mass scraping, rather than targeted extraction. The following points define its scope and practical trade-offs.
- A photograph of the screen beats itOCR, short for optical character recognition, means taking a picture of the page and reading the letters back out of the image. That is what ChatGPT does to an image if you upload one. A photograph of your screen contains all of the correct letters, so they will be recognized normally. The catch is what that costs at scale. Scraping the web means fetching plain text files by the billion, which is very cheap. Photographing the web means drawing every page first and then running image recognition over every picture, and both of those steps cost real money on every page. More on that in § 08.
- Targeted AI can decode itThe font must be sent to the browser so it can display the original words. Anyone who downloads it can therefore inspect it and work out the substitutions. That is unavoidable. But our goal is not to stop someone who deliberately targets a specific site. Instead, it is designed to disrupt large-scale automated scraping, which processes many sites without examining each one individually (because that costs money). ShieldFont currently ships with three different word mappings and gives publishers the tools to create their own, so decoding one mapping does not automatically reveal the others.
- Search engines index the decoySearch engines and AI scrapers read the same source code. This means search engines may index the substituted text instead of the original, which can affect search visibility. Use ShieldFont for archives, essays, and other content that does not depend on search traffic. Leave the parts you need Google to rank unshielded.
- Screen readers have to wait for the textScreen readers (used, for example, by people with visual impairment) work from the source code, where your words are already swapped. The font only fixes things on screen, so a shielded block would be read aloud as fluent, wrong English. Shielded sections in our React tier carry
aria-hiddento stop that. In its place, an opt-in beta ships the correct text encrypted in the page. A button only screen readers reach asks the reader’s browser to solve for the key: a chain of steps where each one needs the answer to the last. It also needs JavaScript, which most scrapers never run. The cost currently lands on the reader: up to twenty seconds on a slow device. That is friction, and it is the part we most want help fixing. - Translation tools read the decoy tooThe same problem breaks translation. Google Translate, and anything like it, reads straight from the source, the same swapped words a scraper collects, so a shielded page comes back as somebody else’s sentence, not yours. We still think about solving this the way we solved it for screen readers, but louder: not a hidden control only assistive software can reach, but a plain button any reader can press to unlock the real text first.
- Copy and paste gives the scrambled textSelecting shielded text copies the source. Inconvenient for a reader quoting you. In the future, we might implement a copy-and-paste filter that restores the original text when it is copied.
- English only, for nowEvery dictionary we have built is in English. Porting one is not simply a matter of translation; it requires a strong ear for the language. Contributions from linguists, native speakers, and language enthusiasts are welcome.
How the meaning moves
Changing a word’s context changes what the model learns from it.
A language model is never told what a word means. It works the meaning out from the words around it.[25]
A sentence, to a model, is the shape drawn between points in a space of meanings (§ 02). What fixes each point is the words that habitually sit near it. Horse lands where it lands because it keeps turning up beside saddle, stable, rider and hoof. Potato lands somewhere else entirely, beside mash, fries and roast.
So when we swap one word for the other, meaning is destroyed because it is relocated. The machine reading the source is handed a new address and records it as ordinary fact.
The distance travelled is the whole design, and it is why we never substitute a synonym. Swapping horse for steed would move the word a few inches and change nothing a model learns from it. Swapping it for potato moves it across the map. § 06 puts a number on that difference. As an example from our study, swapping for synonyms, the kind of substitution a thesaurus would produce, breaks only 2.1% of passages. ShieldFont substitutes words with cohyponyms (a cool term we learned for words that are neither synonyms nor antonyms), breaking between 31% and 56% of passages.
Relocation is also why the technique survives inspection. Some filters are good at identifying gibberish. But there is nothing scrambled about our shielded text. Every sentence is grammatically correct. Every word is real, correctly spelled, and used in a position it could legitimately occupy. Except now it is a sentence with a completely different meaning. And a model will learn that meaning as if it were the new truth.
Why it works, in five steps
Every scraping outcome either blocks the text or pollutes the training data.
A scraper that encounters a shielded page ends up in one of two places. Either the page is discarded before it can train anything, or it enters the dataset carrying meanings the author never wrote. For someone protecting their authorship, both outcomes are a win.
The five steps leading to them are either measured or supported by published sources.
- Scrapers take the source code without drawing the page.A good scraper never reveals their secrets. But based on what is publicly available, most seem to extract webpages without actually opening them. It makes sense economically because rendering pixels costs money. And every extra dollar you have to spend for one webpage, you have to spend for another 999,999. Expensive.[9]
- So they take our swapped words, not our real ones.A font is only consulted when something is being drawn or visualized. Nothing is drawn, so what the scraper stores is the decoy text.
- Quality filters throw most web text away. They throw most of ours away too.The strictest published filter discards around 92% of ordinary web text. In the same way, it discards most shielded pages.[15] That is actually a win: a discarded page never trains anything, which is what our initial goal was.
- But a few pages survive. And when you shield them, 9.70% still pass.Imagine you were to take the pages that cleared that filter. If you shield them, 9.70% still pass. And we used strict filters. Those (poisoned) pages enter the training dataset. This is from one of the tests we ran.
- And those carry the wrong meanings.On a page that survives, 19.4% of the words assert nothing true. And a polluted dataset should eventually degrade a model.[17]
Dropped means they did not get your work. Kept means they got something wrong. The only way it fails is if someone already knows your site is shielded and deliberately works around it, but that is not how mass scrapers currently operate.
How we built it
Changing the meaning less creates more effective disruption.
Between March and May 2026, the dictionary was rebuilt eighteen times. Roughly 1,100 further configurations were built and scored before the final version was chosen.
The starting instinct was word frequency, and it was correct. English is extraordinarily top-heavy: the 100 most common lemmas account for half of all written English.[8] A lemma is a headword and all its inflections counted as one, so be covers is, are and was. The first dictionary we built took the top of that curve: 400 words, swapping the, of and and along with everything else.
That strategy had a pro, but also a con. It turns out that randomly swapping the most common words in English breaks grammar. Like, a lot. It's good because it changes the directions of things. Up becomes therefore, but becomes hug. But that still left exposed domain-specific words that carried most meaning. High-resolution words like neural, quantum and algorithm all stayed unshielded. And language models actually put most of their attention on those exact content words.
So the result was that we did not manage to hide meaning, nor pass filters. One of the filtering scores we looked at, perplexity, scores how surprised a language model is by a piece of text: low means the words fall roughly where the model expected them, high means they do not.[26] Perplexity is like a good way to catch gibberish. In that first version of the dictionary, shielded texts raised perplexity by 1,076%. Now, shielded raises it by only 121%. Past roughly 150%, every filter we tested throws the page away.
The current dictionary determines a 113-word do-not-swap list: pronouns, articles, conjunctions, prepositions, every form of be, have and do, modals, negations and quantifiers. It is a hand-written list, applied at the first stage of the build, before any word is put in buckets. It is also the oldest surviving rule in the system, dating to our seventh dictionary.[7]
With the top of the frequency curve off limits, the dictionary had to grow to hide anything at all. It went from 400 pairs to 1,267 to 11,988 in the current version, working down through the most frequent words specific enough to carry meaning and common enough to appear on a real page.
In the current version, a word is only ever swapped for another word from the same grammatical pool. Not just noun for noun: plural abstract noun about communication for plural abstract noun about communication. There are about 250 such pools, built by crossing part of speech with sense category, concreteness, singular or plural, verb transitivity, verb inflection and adjective degree. Difficult words to say: we are matching grammar (and perplexity, to a certain extent).
Inside a pool, the substitute must never be a synonym, which would change nothing, and never an antonym, which would be a predictable cipher. Of 13,132 candidate pairs built under those constraints, 11,988 survived them. That is why an encoded page reads as grammatical English while meaning something else.
Every build is scored on three quantities.
Concealment is how much of the meaning is hidden. We compute it as the distance between a machine-readable summary of the original passage and a summary of the encoded one.
Filter survival is the share of pages that get past the graders deciding what reaches training. A quality filter is the program a pipeline runs to throw away junk before training begins.
Poison potential is how much a swap changes what the sentence asserts. Something like how wrong a sentence is.
Concealment and filter survival pull against each other, and that tension is the entire engineering problem. Raising concealment lowers filter survival. Held within one recipe family, a 512-cell sweep, the two move together at a Pearson correlation of −0.56: a strong, consistent inverse relationship, not a promise that one point of concealment costs exactly one point of survival. A wider pool of 855 builds across several recipe families reads −0.86, but that number is confounded by mixing dictionaries of different general aggressiveness, so −0.56 is the figure to trust.
So there is a sweet spot. Hide too little and scrapers get your ideas. Hide too much and (1) no scraper keeps the page or (2) they easily spot your text is encoded (and might try to reverse it).
Getting to that sweet spot took two kinds of rule. Twenty-four of them are in the shipping dictionary and are not negotiable: they decide which words are even eligible, how they are pooled, and which pairings are forbidden. Those are the table below. Another thirty were built, measured and thrown away, and because the reasons they failed are the most useful thing we know about this problem, they get their own list in the appendix (§ 13).
24 rules · in v18-alpha
These run on every build, and not one of them can be switched off.
| Rule | What it does |
|---|---|
| The do-not-swap list | Never touch the 113 commonest words (the, of, and, by, is, can). Without it, perplexity hits +1,076% and every filter throws the page away. |
| Closed-class lockdown | Also leave alone frequent words that look like content but behave like glue: get, make, said, day, now, then. |
| Content words only | Consider nothing but nouns, verbs, adjectives and adverbs. Everything else is skipped by default. |
| No names | Never swap a person, place, company or product name. |
| No slurs, units or acronyms | Four blocklists sit in front of everything: profanity, brand abbreviations, proper nouns and measurement units. |
| The one-job test | A word qualifies only if it nearly always plays the same grammatical role. We measure that against a reference corpus and require 80%. A word with no dictionary entry, or one that spreads its meanings across several parts of speech, is dropped. This turned out to be the load-bearing rule of the whole system. |
| Grammatical pools | A word can only be swapped for one from its own pool, about 250 of them, built by crossing part of speech with sense category, concreteness, singular or plural, verb transitivity, verb inflection and adjective degree. |
| Pools of at least four | A pool with fewer than four words is discarded rather than loosened. Too small a pool makes the swap guessable. |
| Stay inside the pool | When words are left over, never rescue them by pairing across pools. We tried, and it produced higher for collaborative and men for hundreds. |
| No near neighbours | Reject the substitute if a machine-readable model of meaning puts it among the 50 closest words to the original, or too close on a similarity score. This, not the dictionary check below, is what really stops synonyms. |
| No synonyms | Reject anything the dictionary lists as meaning the same thing. Swapping a word for its synonym changes nothing. |
| No opposites | Reject antonyms, plus a hand-checked list of near-opposites. An opposite is a predictable cipher, so it can be undone. |
| No broader or narrower word | Never swap a word for its category or an example of itself, like dog for animal, following the chain all the way up and down. |
| Not the same word in disguise | Reject the pair if both words share a root, so running never becomes ran. |
| Same dictionary role | Both words must have the same main part of speech according to the dictionary, not just the same guess from the sentence they were found in. |
| Verbs must fit the same sentences | Two verbs can only pair if they accept substantially the same sentence shapes, measured against a database of verb patterns. This is the rule that keeps wave the music rarer than it would otherwise be. |
| Every pair works both ways | If A becomes B then B becomes A, always. The whole dictionary is its own reverse, which is what lets a single font undo it. |
| Eight retry rounds | Words left unmatched get reshuffled inside their pool and tried again, up to eight times, against the exact same filters. Nothing is waved through to fill a gap. |
| Fluency rerank | Rather than pair words at random inside a pool, rank them by how ordinary each one sounds and pair neighbours in that ranking. Roughly tripled filter survival for 51 lost pairs, the only rule that bought survival for free. |
| Inflection families | Once a word is paired, its other forms are generated and paired to match, each one rechecked against the rules above. This is 1,456 of the 11,988 shipped pairs. |
| Dates get their own shuffle | Months, weekdays, ordinals and time words are not paired by meaning at all. They rotate by a fixed offset, so every month moves six months on and every weekday moves three days on. |
| Digits move, years stay years | Digits swap in fixed couples (0 with 5, 3 with 8, 4 with 9, 6 with 7), and written numbers follow the same couples, so zero becomes five. 1 and 2 are deliberately left alone so that 1990 and 2024 still read as years and not as nonsense. |
| One decoy, one original | Before the font is built, any decoy that could stand for two different originals is removed. If the reverse were ambiguous the font could not render the page correctly. |
| The round-trip audit | Every pair in the finished font is checked to come back as the original word in lower case, Capitalised and ALL CAPS, and no short pair is allowed to fire inside a longer word. |
Results
Fifteen to twenty-seven times more destructive than swapping with synonyms.
Every number in this section was measured on v18, the eighteenth build of the dictionary and the one running on ShieldFont today. They are current numbers, and they should improve with future builds.
We still need to know one important thing: how different is the shielded version of a text relative to the original text?
The instrument to measure that is an entailment classifier: a public model, built by other people, that judges whether one sentence follows from another.[27] We run it in both directions and count a passage broken only when the original no longer implies the encoded version and the encoded version no longer implies the original. A failure in one direction only does not count.
The design is four corpora (four types of texts: older fiction, fiction, general web content, news articles), 1,000 passages each, against two controls. The first control leaves the text untouched and gives the instrument’s own error rate. The second swaps words at exactly our rate but for their synonyms, holding the amount of disturbance fixed and changing only whether the substitute means the same thing. That second control is what separates real meaning loss from a classifier being unsettled by unusual vocabulary.
The two controls come first because they are the floor, and the four corpora then climb from the one that resists the technique hardest to the one that gives way most.
| Text | What it is | Passages that stop making the same claim | Versus the synonym-swap control |
|---|---|---|---|
| The floor · what no effect looks like | |||
| Untouched control | the original text, unchanged | 1.1% | instrument noise |
| Synonym-swap control | same swap rate, synonym words | 2.1% | baseline |
| Shielded · weakest corpus first | |||
| PG-19 | older fiction | 31.1% | 15× |
| BookCorpus | fiction | 34.5% | 16× |
| OpenWebText | general web writing | 51.9% | 25× |
| CC-News | news reporting | 55.8% | 27× |
1,000 passages per corpus. The synonym control is the load-bearing row: at 2.1% it sets the floor that the technique has to beat to have done anything at all.
One thing about how this was run. The experiment was pre-registered on three corpora, where the median was 50.4%. A fourth corpus, a second body of fiction, was scored afterwards and pulled that median to 41.8%. Both figures are honestly computed and they differ only in which corpora are counted. Reporting per corpus makes the choice moot, and the comparison that carries the argument does not move: at our weakest we are fifteen times a synonym swap, and on news, twenty-seven.
The waste figure describes a scraper’s day. On a page that survives the quality filter, 19.4% of the words are training-time garbage: real English, correctly spelled, asserting nothing true. That is the figure across all four corpora. Across the first three it was 24.1%, the same corpus-count difference that moved the entailment median. It needs no claim about what happens to a model, because it is a property of the page and it was measured on the page.
The gap between the two coverage figures is deliberate. A quarter of all running words are swapped, but 45.8% of the meaning-carrying words are, because the, of and is are left alone on purpose (§ 05). The budget is spent where it buys something.
On the filter, the number is about one in ten. Of the pages that would have cleared a real pipeline’s educational-quality grader before shielding, 9.70% still clear it after: 13 out of 134. It replicated at 10.27% on a different three corpora with a different scoring harness, so the result holds across six corpora and three separately seeded dictionaries.
Two caveats travel with it. The denominator is small, and the 95% confidence interval runs from 5.8% to 15.9%. And in absolute terms the rate is 0.38%, because that grader keeps only 3% to 7% of unshielded web pages in the first place. The conditional rate is the one that answers the question being asked, which is what shielding costs a page that would otherwise have been taken.
We ran four graders over the same pages and they disagree with each other almost completely. The rank correlation between them is close to zero. Retention runs from 2% to 65% depending on which grader you ask, with a median of 12%, so a page one grader discards, another keeps. That is why we refuse to tune against any single one. A page only has to survive the grader a given pipeline actually runs, and nobody outside those companies knows which that is.
One hundred pages, judged by a deliberately harsh stand-in filter
No lab publishes the filter it really runs, so we borrowed a strict public one and assumed the worst for ourselves.
a win for the author
also a win for the author
What it actually looks like
Two passages from the same corpora, both scoring the maximum on the meaning-loss measure. Words in terracotta are the substitutions. Names, dates and anything outside the dictionary pass through untouched, which is the point: the page keeps every marker that makes it look reliable.
We don’t know what they use
We do not know every filter in use, but shielded text passes those we can test.
A reasonable question: how do we know we are testing against the filters that actually get used? We do not, and it is simply not possible. We have worked based on six publicly available scraping pipelines (§ 08). Whatever a given lab runs this year is not among the things anyone outside it can read.
So we test against the strictest gates that are published. The hardest is a classifier trained to keep only educational-quality writing —the one that discards 92% of ordinary web text.[15] Yes that was an em-dash. Let a man live a little. We grade ourselves against that one on purpose, and try to make the cut throughout all disagreeing filters (§ 06).
Which turns the awkward-looking number (9.70% making it past filters) into the strongest one we have, because it's a conservative cut. The quality filter is a good detector for our pipeline. It is the tool built to notice text that is off, by the people whose job is noticing.
It catches nine in ten of our pages. But it also makes the tenth page precisely the fraction the best known public detectors could not tell apart from ordinary writing.
One flip side. A lab might deliberately want unusual text: surreal poetry fails conventional filters while being genuinely novel material, and a team hunting for range might reach for the exact type of text we offer: correct but weird English. That could be a different game, and an interesting one. A dictionary tuned for strangeness rather than for passing.
Chaos is the enforcement mechanism
It is impossible to scrape a moving target.
Those six major published dataset pipelines (FineWeb, DCLM, RefinedWeb, C4, The Pile and Dolma) extract text from raw archived HTML. None runs a browser, executes JavaScript or turns a page into an image, and across all six papers there is not one mention of any browser-automation tool.[9]
C4’s (one of the pipelines) reports that many of the scraped pages contained warnings stating that Javascript should be enabled, “so we removed any line with the word Javascript.”[9]
The closest thing to an exception is a 2025 NVIDIA maths dataset, which routes pages through Lynx, a text-only terminal browser, and whose claim is to be the first pipeline to use a browser at all. Lynx follows layout rules. It never hunts down through divs and downloads a font. It never draws a pixel, so shielded text passes through it unchanged.[10]
Live traffic data points the same way. Across one content network in a single month there were 569 million fetches by OpenAI’s crawler and 370 million by Anthropic’s, and neither executed JavaScript. However, two more advanced crawlers do draw full pages, AppleBot and Google’s Gemini (and ShieldFont might not work here for now).[11]
Both Google and Apple are endorsed by a 2022 security paper called Bad Characters, which recommends drawing every page and photographing/OCRing it as the “catch-all defense”.[12] They are right about the mechanism. The disagreement is about the legitimacy, because at web scale every cent drags.
Drawing a page instead of fetching it costs five to about thirteen times more, a multiplier three scraping vendors publish openly.[13] Reading three billion pages with the cheapest published self-hosted OCR runs to roughly $528,000. For scale, Common Crawl’s entire 2024 budget was $1,326,638, for 26.67 billion pages across ten crawls.[14] The OCR pass alone would eat 40% of the foundation’s annual money to reach 11% of its pages.
But first they have to know which pages to invert. And what to invert within each page. That is the hard part, and the part we control. If crawlers can spot a shielded page cheaply, the cheapest response is to drop it and move on. If they choose to persevere, they have to put in some money to understand the intricacies of each webpage (which vary, non-deterministically). OCRing the whole internet would, therefore, be the only way around the shield, and it is expensive enough to make that a non-starter.
So the effort goes into being hard to crack. A single page can carry several dictionaries across different paragraphs, so an attacker has to work out which block goes with which font before decoding anything. Our component supports that, and it is the recommended deployment.
Beyond that, no two sites are configured alike: a renamed class, a different font path, the whole site or a single paragraph. Decoy markers could put fake shield classes and fake font names on unshielded text, so a fingerprint built by reading the page lies to whoever built it. And nothing in the bytes we serve says “ShieldFont”: the font names are neutral, the class is neutral, there is no version string, and the shipped font either drops its glyph names outright or hashes them, so the file never spells out in plain text which word a given shape draws.
So for as long as we keep our code chaotic enough, a scraper cannot make sense of shielded content at scale. They would need someone (or some AI model) to expensively dedicate attention to each page. They are better off either (1) dropping your content altogether, or (2) changing their entire scraping pipeline to OCR the whole internet.
One honest tell remains, and it’s optional. A full, unsubsetted font carries a glyph for every word in the dictionary, about 825KB for the whole 12,011-pair vocabulary, and file size is a signal. A build-time subsetter ships only the glyphs a page’s own content can trigger, the way Tailwind ships only the CSS a page uses, cutting that by up to 78%, down to roughly 82KB for a typical page. It also makes the font unique per page, which is a good thing.
Every fruit looks identical by default: that is the whole argumentonly the x-ray tells them apart. Six of twenty-four are shielded here, one in four.
Beyond a typeface: other implementations
ShieldFont grows stronger when others build their own versions.
The idea is one sentence: show one thing for humans, something else for machines.
ShieldFont is one way to do it. There are many others and we want to build them. And our main underlying purpose is to enforce a basic principle of AI ethics: creators should have a meaningful say in whether their work is used to train AI systems. Where consent is not respected, technical design can make taking that work without permission less useful and more costly.
This is not an anti-AI stance. We would not have built this whole thing without AI. This is a stance in favor of compensation, and credit. And to state publicly that being discoverable does not mean consenting to AI training. As a collective.
Anything one team ships has consistent tells, and given enough examples, adversarial actors will learn to bypass it. But a technique that ten independent projects implement in ten incompatible ways has nothing consistent to learn. This is the rare case where a competitor makes us stronger. A competing, incompatible implementation of this idea would be a success, not a threat. If you build one, we will link to it.
And it compounds. One shielded page contributes one page of wrong data. 19.4% of that page is asserting nothing true (§ 06). What scales is the number of pages, and the moment when your pages also start belonging to other people. When a horse becomes a potato.
What we are standing on
People have done pieces of this before.
Font-level defences against machine reading are about a decade old, and most of them have been broken in public. That is the useful part of the history, and it is why we argue from cost rather than from secrecy.
Chinese websites have remapped fonts against scrapers since at least mid-2016. The best evidence is production HTML rather than a paper: an archived capture of Maoyan’s box-office page from August 2016 serves its numbers as private-use codepoints behind a custom web font, and captures from February and April that year do not.[18] The counter-technique is published too, in practitioner write-ups rather than research: one reports recovering 602 glyphs in about three seconds, another defeats a site that rotates its font on every visit.
TuringFonts (2015) published a letter-for-letter cipher font to stop harvesting of email addresses and phone numbers.[19] A quality filter throws its output away as gibberish, and a model recovers the plain text by letter frequency in a single pass. Sang Mun’s ZXX (released May 2012, six cuts) is a typeface built to defeat text-scanning at the letterform.[20] Ross Anderson’s verdict on it at the time was “I don’t think any of this is more than privacy theater. The fonts could probably be broken.” He was right, and the same is true of ours (§ 08).
Nightshade[21] and Glaze brought poisoning and protection to images. Both have since been defeated by published attacks,[22] and that is the most useful thing about them for anyone building in this area: a protection whose value depends on remaining unbroken has a short life.
LayerX’s 2026 “Poisoned Typeface” uses the same gap between what a page draws and what its source says, in the opposite direction.[24] There the render is the attack and the source is the alibi: the person sees the payload and the assistant reading the page sees something harmless. Every non-agentic assistant they tested failed to notice.
Nobody has applied font-level word substitution to protecting training data. That is the whole of the novelty claim. The two academic papers that use the same primitive use it to attack.[23]
How to deploy it
Five routes, in descending order of how much they conceal.
- Put up a robots.txt first. Always.State your terms in the way everyone has agreed on, even though it is only a request (§ 01). ShieldFont is what you do when the request is ignored: standing your ground, not throwing the first punch.
- React, rendered on your server, or built into static pagesThe recommended route: your real text becomes decoys before it leaves your machine. Do not mark those components
"use client", which ships the real text to the browser and hands a scraper both versions. - Paste-in from a CDN, for blogs and static sitesEasiest to try, least concealed, because the setup is identical everywhere it is used. Good for experimenting, not as a default.
- A downloadable font, for documents and emailFor Word documents, PDFs and email, where the same substitution hides the original text from AI tools that read the file directly.
- Use several dictionaries across one pageIf your setup allows it, the single highest-value thing you can do (§ 08).
Note: ShieldFont can be applied selectively, block by block, allowing publishers to leave SEO-critical or accessibility-dependent content unchanged. Use it alongside existing security and crawler-control tools, not as a replacement for them.
Where we want help
Six things would move this, and the first one is linguists.
An open process, nowhere near finished. Six things would move it, in descending order of how much difference they would make.
- Linguists, first and mostv18 is version one. Better word pairs would read more naturally and survive more filters, and the register-matching rule in § 05 sits unshipped because we could not make it pay. The highest-value contribution anyone could make.
- Other languagesEvery dictionary we have built is in English. Adapting one to another language is not simply translation; it requires a strong feel for how that language works. We welcome contributions from linguists, native speakers, and language enthusiasts.
- AccessibilityShielded blocks are hidden from assistive software. We need to find every way possible to make them readable to more people. Currently looking for a better solution to re-render text back into the page without showing it to crawlers, to comply with accessibility standards. We already have a solution in beta, please check our docs for more information.
- Anyone with computeWe want to know what happens to a model actually trained on this at scale, and that takes a pretraining run we cannot afford. If you can, we will hand over everything and publish whatever comes back, including a null result.
- Other implementationsBuild a different one, incompatible with ours (§ 09).
- Adversarial researchersBreak it in public. The highest-priority test is automated detection and reversal across many differently configured sites.
Appendix: the rules we cut
Thirty rules were built, measured and thrown away.
The twenty-four rules in § 05 are what survived. These are what did not. Almost every one is right in principle, which is why each row says what we measured rather than simply that it lost. Several are still open work for anyone who wants them (§ 12). Most of the counts below trace to a committed script or a published research file; a minority, roughly a fifth, trace only to internal notes and are measured but not independently reproducible from the shipped benchmark data.
30 rules · cut before v18
Every line is what the rule would have done, not what happens.
| Rule | What it does |
|---|---|
| Switching the date shuffle off | Would have deleted the date and number rotation above and left months, weekdays and number words untouched. There is a real case for it: across 120 sample pages we found 26 date swaps, and 12 of them clearly damaged the text, like 1963 becoming 1478. An entire sweep was built to test this one toggle, and rotating them won anyway, so the rotation stayed. |
| Selectional restriction | Would have required a verb and the thing it acts on to make sense together, so you can eat food but never eat ideas. Our sample check found only four clear violations, too few to justify the cost. Bundled with the fixed-phrase rule below it dropped content coverage from 46% to 21%, and on its own it never paid for itself either. |
| Fixed-phrase freeze | Would have left set phrases alone, so take up arms, make sure and for instance survive whole. This is a genuine problem: 18 phrases were broken across 120 sample pages, including take up arms turning into recommend up pants. Every setting we tried still cost more concealment than the naturalness it bought. |
| Register matching | Would have stopped formal words being swapped for casual ones, so a legal document does not suddenly read like a group chat. It flags more than almost anything else we built: 68 swaps across 120 pages changed the tone of the writing. It never produced a winning build, which is exactly why it is the most valuable thing a linguist could pick up. |
| Family versus stranger | Would have kept words for relatives apart from words for strangers, so mother never becomes stranger. We only noticed it hiding inside the register problem above, in swaps like family becoming jury and parents becoming colonials. It was never built as a rule of its own, because register matching, the broader version of the same idea, could not be made to pay. |
| Quote-verb freeze | Would have frozen the verbs that introduce speech, so said, asked and replied stay put. Worth doing: said becoming clutched turned up in 8 of 120 sample pages, and it wrecks every line of dialogue it touches. Rather than ship as a separate rule it was folded into the closed-class lockdown, which does ship. |
| Surprising-pair blacklist | Would have banned any swap that leaves the two words around it reading oddly to a language model, like this kind becoming this calorie. It found 15 such swaps across 120 pages, but nearly every one had already been caught by the do-not-swap list or by register matching, so it added almost nothing of its own. |
| Two-word gate | Would have run one final check over the finished dictionary, throwing out any pair that left an implausible two-word sequence behind. It was one of the six switches in the main sweep, and every build that turned it on read worse than the same build with it off. |
| Pointing-word restriction | Would have kept the words that point at a time or a place in a group of their own, so now, here and again can only swap with each other. Left alone they drift into words about manner instead: now becomes obviously, away becomes strictly, again becomes strongly. Folded into the closed-class lockdown rather than shipped on its own. |
| A second slur filter, and year bands | Would have added a further offensive-word filter on top of the profanity blocklist that already ships, and kept every swapped year inside its own decade, so 1990 could only become another year in the 1990s. In the main sweep, every build with it switched on read worse than the same build without it. The blocklist above is a separate rule and still runs. |
| Frequency-band cap | Would have allowed swaps only between words of roughly equal commonness, so a very common word could never become a rare one. We built it and set it to allow half a step of difference. It threw away so many usable pairs that coverage collapsed, and it has been switched off since the sixth dictionary. |
| Rarity cap | Would have refused to use any word rarer than a set threshold as a decoy, so a reader never meets a word they have never seen. We tried five thresholds, but all five only ever ran inside a from-scratch rebuild that collapsed as a whole: perplexity landed 245% above normal and under 1% of pages survived the filters. None of them got a clean reading on its own. |
| Rare-pair drop | Would have thrown out finished pairs where both words are uncommon, on the theory that two rare words side by side look suspicious to a filter. It changed nothing measurable, because words that rare are under 1% of the words on an ordinary page. Adding 50 of them back scored the same as the shipping dictionary on every measure, to four decimal places. |
| Same-category reward | Would have preferred pairs from the same sense category rather than banning mismatched ones outright, a gentler version of the pool rule above. Like the rarity cap, it only ever ran inside the rebuild that collapsed, so it never got a fair test. |
| Importance weighting | Would have spent the swaps on the words carrying most of a page's distinctive meaning, instead of treating every eligible word alike. Same story: it existed only inside the failed rebuild, so there is no clean result for it either. |
| One-main-meaning test | Would have used a word only when one of its meanings clearly dominates the others, so bank always means the money kind and never the river kind. Tested at a strict setting and a loose one, both inside the rebuild that collapsed. |
| Modal swapping | Would have allowed can, may and must to be swapped instead of frozen. Only three pairs could be built at all, and when a person checked them, none of the three made sense. Swapping a modal changes whether a sentence says something is possible, permitted or required, which is not a thing you can decide without reading the sentence. They stay frozen. |
| Drop the inflection families | Would have shipped only the directly paired words and thrown away every generated word form, roughly 1,400 pairs. It did buy 2.4 percentage points of filter survival, but concealment fell and the text drifted back so close to ordinary English that it fell out of the range we aim for. The wrong trade in the direction we care about. |
| Feeling match | Would have required both words to carry the same emotional charge, so a warm word never becomes a cold one. It caught too few pairs to move any measurement: every difference it made was under half a percentage point, which is inside the noise of our own testing. |
| Adjective-from-noun match | Would have treated adjectives coined from nouns, like dental from tooth or nasal from nose, as a category of their own. The effect was pure noise, smaller than the gap between two runs of the same grammar check on the same dictionary. |
| Tighter concreteness match | Would have narrowed the concrete-versus-abstract bands the pools already use, so a thing you can touch never becomes an idea. The same trade as dropping the inflection families: 2.3 percentage points of filter survival, paid for with concealment and with the text drifting out of the range we aim for. |
| Ambiguous noun-verb additions | Would have added back the words that work as both noun and verb, like time, way, work and use, which the one-job test throws out. This was the great hope for the next dictionary and it failed twice: 18% of the new pairs were acceptable on the first attempt, and 12% after we fixed the tense matching. Two words both being a noun and a verb tells you nothing about whether their meanings line up, which is how you get wave the music where face the music was meant. Pushing it further raised perplexity by 77 points and cost 6 points of filter survival. |
| Maximum-difference pairing | Would have stopped pairing at random inside a pool and instead solved for the arrangement that makes every pair as distant in meaning as it can be. We tried it in both directions. Pairing for similarity kept too much of the original meaning intact. Pairing for maximum difference hurt every measure at once, filter survival included, with no upside anywhere. |
| Tense alignment | Would have required two verbs to share at least one tense form before they may pair, catching slips like discovered becoming defines. It cost 523 pairs and a slice of concealment, and bought 0.6 of a percentage point of filter survival. |
| Singular and plural match | Would have caught the singular-for-plural swaps that slip past the pools. It found only 95 pairs to remove and bought 0.1 of a percentage point of filter survival, for a small loss of concealment. |
| A wider acronym purge | Would have gone further than the brand-abbreviation blocklist that already ships, dropping every short word that behaves more like an abbreviation than a word. It removed 154 pairs and returned 0.6 of a percentage point of filter survival, at one of the larger concealment losses of the six checks in its sweep. |
| Comparative purge | Would have caught comparative and superlative forms that landed in noun pools by mistake, like browner paired with keener. It removed 122 pairs and changed nothing whatsoever: filter survival moved by exactly zero. |
| Forced-plural purge | Would have dropped the words that only exist as awkward plurals of things you cannot count: knowledges, violences, awarenesses. It was the most destructive of the six checks in its sweep, removing 1,291 pairs and taking the largest concealment loss of the group, for 0.6 of a percentage point of filter survival. |
| Category recheck for nouns | Would have re-checked every noun pair against the dictionary's own category, catching the cases where the pool said one thing and the dictionary said another, like fellow paired with wad. It is the only one of the six that made both numbers worse at once: concealment fell, and filter survival fell with it. |
| Function-word pairs | Would have swapped the glue words, the, of, and, in matched sets instead of leaving them alone. The table was built and never switched on. The do-not-swap list exists precisely because swapping these words pushed perplexity to 1,076% above normal and every filter threw the page away. |
Every configuration, sweep and rejected hypothesis is in the benchmark directory of the public repository.
References
A [1]-style marker in the prose above jumps straight to its entry here; the title of each entry links out to the primary source where one could be verified.
- [1] Richner Communications et al. v. Microsoft & OpenAI (2026)S.D.N.Y. No. 1:26-cv-05320, filed 24 June 2026The 400-newspaper suit. Pending, like every other: no US news publisher has settled an AI-training copyright case.
- [2] Varoufakis, Y. (2023)The Bodley Head, ISBN 9781847927279. Link goes to the free companion essay, “Techno-Feudalism Is Taking Over,” Project Syndicate, 28 June 2021, since the book has no single canonical URL.Coins the term for this paper's purposes: capital reproduced by unpaid user labour, with extraction shifting from profit to rent. A contested frame, not settled analysis; Evgeny Morozov's rebuttal (New Left Review, 2022) argues it risks flattering capitalism's own long history of dispossession.
- [3] Terranova, T. (2000)Social Text 18(2)(63): 33–58The canonical free-labour argument. Extended to AI training data by Morreale et al., AI & Society 39(5) 2024, and to behavioural data by Zuboff (2019).
- [4] Villalobos, P.; Ho, A.; Sevilla, J.; Besiroglu, T.; Heim, L.; Hobbhahn, M. (2024)ICML 2024, PMLR 235:49523–49544Exhaustion of the public human-text stock between 2026 and 2032, median 2028. The same team later put the binding constraint elsewhere.
- [5] Koster, M.; Illyes, G.; Zeller, H.; Sassman, L. (2022)RFC 9309Crawlers are “requested to honor” the rules, and “these rules are not a form of access authorization.” It provides no way to compel compliance.
- [6] Kim, T.; Bock, K.; Luo, C.; Liswood, A.; Poroslay, C.; Wenger, E. (2025)ACM Internet Measurement Conference 2025130 bots, 40 days. AI crawlers rank among the more compliant categories, and the authors still conclude that relying on robots.txt “is risky.”
- [7] Rae, J. W.; Borgeaud, S.; Cai, T.; Millican, K.; Hoffmann, J.; et al. (2021)arXiv:2112.11446, DeepMindThe primary source for the do-not-swap rule, and inherited by RefinedWeb, FineWeb and Dolma.
- [8] Oxford English Corpus; Gilner, L. (2011)Reading in a Foreign Language 23(1): 65–83, tabulating Leech, Rayson & Wilson (2001)Top 100 lemmas are 50% of written English; top 100 distinct spellings are 45.89% of the BNC. The counting unit matters and is stated every time.
- [9] Penedo et al.; Li et al.; Raffel et al.; Gao et al.; Soldaini et al. (2019–2024)FineWeb, DCLM, RefinedWeb, C4, The Pile, Dolma.All six extract text from raw HTML. Searched in full for every browser-automation term: zero hits.
- [10] Karimi Mahabadi, R.; Satheesh, S.; Prabhumoye, S.; Patwary, M.; Shoeybi, M.; Catanzaro, B. (2025)arXiv:2508.15096, NVIDIAThe one pipeline we found that uses a browser at all, and it says so itself: “to our knowledge, this is the first work to employ the text-based browser Lynx.” Lynx follows layout rules, does not execute JavaScript, and never loads a font, so it is not an exception in the way that would matter.
- [11] Zecchini, G.; Moore, A. A.; Ubl, M.; Siddle, R. (2024)Vercel Engineering Blog, with MERJ, 17 December 2024“None of the major AI crawlers currently render JavaScript.” Vendor post, not peer-reviewed, one network’s traffic, data not released.
- [12] Boucher, N.; Shumailov, I.; Anderson, R.; Papernot, N. (2022)IEEE Symposium on Security and Privacy 2022, pp. 1987–2004Recommends render-and-OCR at a 6.2% accuracy cost it frames as low. Our answer is web-scale economics, not a claim that OCR is hard.
- [13] ScrapingBee; ScraperAPI; Zyte (2026)Published credit and price schedules for a rendered request versus a plain fetch.1 credit against 5 (5.0×), 1 against 10 (10.0×), and $0.13 against $1.01 per thousand requests (7.8×, rising to 12.7× at the top tier). The cheapest ratio any of the three publishes is 2.5×, on a premium-proxy tier, which is why § 08 gives a range rather than a single multiplier.
- [14] Commoncrawl Foundation; Poznanski, J.; et al. (2025)Form 990-PF Part I line 26 · arXiv:2502.18443v3Total expenses $1,326,638 against ten 2024 crawls totalling 26.67 billion pages. olmOCR gives the cheapest published OCR rate, $176 per million pages.
- [15] HuggingFace (2024)huggingface.co/datasets/HuggingFaceFW/fineweb-edu“This removed 92% of the dataset.” The strictest public quality filter, and our primary gate.
- [16] Biderman, S.; Schoelkopf, H.; Anthony, Q. G.; et al. (2023)ICML 2023, PMLR 202:2397–2430The controlled precedent for what swapped words do to a model, and the closest thing to evidence for the claim we deliberately do not make. Resuming training on identical data with masculine pronouns replaced by feminine ones reduced stereotypical bias at every size tested (70M to 6.9B), flipping the largest outright. The authors hypothesise, but do not demonstrate, that the effect grows with scale. See also Schuster et al., IEEE S&P 2020.
- [17] Guo, X.; Peng, R.; Tong, J.; Zhou, Y.; Lv, H.; Lu, Z.; Guo, Q. (2026)arXiv:2605.10129Cited against ourselves. At 10% corruption of a small model’s pretraining data, validation loss moves 0.032 nats and downstream scores stay inside their error bars. The best published reason to think a small dose does nothing, and why § 04 stops at the dataset.
- [18] piaofang.maoyan.com (2016)Internet Archive capture, 14 August 2016The primary evidence for dating font remapping on the Chinese web, and better than any secondary account. That capture carries an @font-face rule with live CDN URLs and 176 private-use codepoints, with the box-office total rendered entirely in them. The February and April 2016 captures have neither, which is why § 10 says mid-2016 rather than the widely repeated 2015.
- [19] jfmdev (2015)github.com/jfmdev/TuringFonts, created 14 April 2015, ten commitsA letter-for-letter substitution-cipher font, self-described as a “technique to publish uncrawable and uncopiable texts” (sic), for hiding email addresses and phone numbers from indexers. Hobby scale, and reversible by inspection.
- [20] Mun, S. (2012)ZXX.released May 2012; described by the designer in “Making democracy legible: a defiant typeface,” Walker Art Center, 20 June 2013Six cuts (Sans, Bold, Camo, False, Noise, Xed), drawn to be unreadable by text-scanning software. Ross Anderson, Professor of Security Engineering at Cambridge, in CNN’s October 2013 coverage: “I don’t think any of this is more than privacy theater. The fonts could probably be broken.” We found no study testing modern optical character recognition against it, and do not claim one exists.
- [21] Shan, S.; Ding, W.; Passananti, J.; Wu, S.; Zheng, H.; Zhao, B. Y. (2024)IEEE Symposium on Security and Privacy 2024, arXiv:2310.13828The image-side precedent, and its authors propose it in the same terms we do: “a last defense for content creators against web scrapers that ignore opt-out/do-not-crawl directives.” Fewer than 100 poison samples corrupt a Stable Diffusion XL prompt. Defeated the following year by LightShed (Foerster et al., USENIX Security 2025, pp. 7271–7290), which detects and strips the perturbation at a 99.98% true-positive rate.
- [22] Hönig, R.; Rando, J.; Carlini, N.; Tramèr, F. (2025)ICLR 2025 Spotlight, arXiv:2406.12027The Glaze break, covering Glaze, Mist and Anti-DreamBooth. Those tools “are ineffective when faced with simple robust mimicry methods” and “merely provide a false sense of security.” Cited against ourselves: it is why nothing here rests on the font staying unread (§ 08).
- [23] Xiong, J.; Wei, M.; Han, X.; Lu, Z.; Liu, Y. (2025)IEEE Transactions on Information Forensics and Security 20: 8773–8787Names the primitive “glyph-code mismatch” and uses it offensively. Its companion paper, arXiv:2505.16957, is the reason our novelty claim is limited to the defensive application.
- [24] Paz, R. (2026)LayerX Security, 17 March 2026The same gap between source and render, weaponised in the opposite direction. Every non-agentic assistant they tested failed to detect it.
- [25] Harris, Z. (1954)Word 10(2–3): 146–162The distributional hypothesis: a word's meaning is worked out from the company it keeps, not stated anywhere. The premise this whole section rests on.
- [26] Jelinek, F.; Mercer, R. L.; Bahl, L. R.; Baker, J. K. (1977)Perplexity, a measure of the difficulty of speech recognition tasks.Journal of the Acoustical Society of America 62(S1): S63Where the term comes from, decades before it was repurposed as a language-model quality filter.
- [27] Sentence-Transformers (2021)HuggingFace model card, fine-tuned from microsoft/deberta-v3-base on SNLI + MultiNLIThe public entailment model that § 06 runs in both directions.
- [28] Microsoft Typography; Adobe (1996)Jointly developed by Microsoft and Adobe from 1996The ligature mechanism this paper's whole metaphor rests on, thirty years old as of this paper.