TL;DR: I built a single Edge Function on Tencent EdgeOne that decides in under 20ms, whether a request is a trusted app, a search engine, or an unverified scraper, and answers each one differently. One gets the real thing. One gets a red carpet. One gets a beam swapped for rotten wood. It is designed to sit on top of EdgeOne's new AI Bot Management, it's live, and the code is open.
The wall was never about blocking
People think the Great Wall of China was built to keep enemies out.
It wasn't, not entirely. At checkpoints like the Yumen Gate, guards didn't have one lever. They had judgment. Citizens walked through. Merchants traded, taxed but welcomed. Bandits pretending to be merchants got caught then sent back holding nothing.
Modern infrastructure has one lever: block, or don't. That's not a checkpoint. That's a locked door.
Two problems, one blunt tool
Run an app that generates dynamic Open Graph preview cards, and you'll hit this fast. Every card gets rendered server-side, every time it's requested real compute, real cost, for the same handful of images, over and over.
Then AI scrapers show up. Same endpoint, same assets — pulled at scale for reuse, indexing, dataset collection, or potential model training—without a license, attribution, or contribution back to the creator.
The standard defense is 403 Forbidden. But bots built on AI now spoof TLS fingerprints and user agents well enough to pass for a real visitor. Block hard enough to catch them, and real users start getting caught in the same net.
You don't need a bigger wall. You need a checkpoint with judgment — three ancient tactics, running at the edge, in code.
Tactic One: 借刀杀人 — kill with a borrowed knife
Tencent EdgeOne just upgraded Bot Management with a dual-engine approach: AI-generated rules for the obvious cases, and AI risk scoring for the gray zone, the traffic that looks human enough to slip past a blocklist, but isn't.
That's the borrowed knife philosophy. Bots powered by AI are the threat; EdgeOne's own AI is the weapon. I didn't build a bot detector from scratch — my Edge Function is designed to sit on top of EdgeOne's new dual-engine Bot Management. It applies the same 'fight AI with AI' philosophy, but one layer up: not just deciding whether to let someone through (threat or not), but deciding what they get when they do.
The architecture: one gate, three verdicts
🟢 Citizen — Valid HMAC-SHA256 signature → full-resolution, clean SVG.
🔵 Merchant — Verified search / AI answer engine → structured SVG + JSON-LD.
🔴 Bandit — Everyone else, by default → a swapped, degraded SVG.
Tactic Two: 无中生有 — something from nothing
A plain image tells a search engine nothing. No name, no description, no context — just pixels. State 2 fixes that honestly: when a verified crawler or AI answer engine requests the card, the response includes real, accurate structured data (JSON-LD) describing exactly what the image is.
This isn't a trick — it's the opposite of one. It's Generative Engine Optimization done straight: give the machines that will summarize your content to real people something true and well-structured to work with, where before there was nothing but a bitmap. The "something from nothing" is legitimate value, created once, served instantly, at the edge. We bypass the expensive origin server entirely, feeding LLMs exactly the context they need while our backend compute bill stays at zero.
Tactic Three: 偷梁换柱 — steal the beam, swap the pillar
This is the one worth slowing down for.
The old stratagem: an enemy believes they're stealing a load-bearing beam. What they actually walk off with is rotten wood, swapped in before the theft ever completed. They don't find out until the structure they build on it collapses.
State 3 is that, exactly. An unverified scraper requests the same endpoint a real user would. It gets a 200 OK — no error, no red flag, nothing to signal that anything went wrong. What it downloads instead is a visibly degraded image, stamped with a copyright notice it cannot avoid ingesting. The scraper's pipeline completes successfully. It just built on rotten wood.
This is not a bot blocker or a DRM system. It is an edge-native, policy-driven mitigation layer for unverified scraping and unauthorized asset harvesting. Trusted applications receive the original asset; verified discovery systems receive truthful, machine-readable context; and unverified harvesting receives an intentionally degraded representation designed to carry less training and commercial value.
Design note (for asset production, not for the reader): this is the money shot — make the degradation unmistakable, not decorative. Apply
<feGaussianBlur>or<feColorMatrix>across the entire image, not a corner effect, designed to carry materially less reuse, training, and commercial value. The copyright text must overlap the main subject directly, not sit in a small corner badge easy to crop out. The goal is not merely to label the copy, but to make it materially less useful. If a scraped copy retains most of the original’s reusable value, the swap has not achieved its purpose.
What the gate protects: asset value, not just bandwidth
The real target is not merely traffic volume. It is the value of an asset once it leaves the origin: original visual quality, reusable detail, attribution, and machine-readable provenance.
A blanket 403 can create false positives while signaling to persistent scrapers that they have hit a protected endpoint. This gate instead applies an IP-aware delivery policy. It preserves a clean path for authorized applications, supports legitimate discovery through accurate JSON-LD, and limits the utility of assets obtained by unverified harvesters.
The goal is not to claim perfect protection. No public asset can be made impossible to copy. The goal is to make unauthorized bulk collection less useful, more attributable, and easier to observe—without breaking legitimate users or search visibility.
The bug that would have swapped nothing at all
Here's the part most write-ups leave out, and it's the part worth reading closest.
My first version of the routing logic checked for a valid signature; if that failed, it checked whether EdgeOne flagged the request as high-risk; if that failed too, it fell through to the clean SVG. State 1. The privileged lane.
I hadn't written "prove you belong here." I'd written "if nothing looks dangerous, assume you do." Any scraper polite enough not to trip a risk score — no weird pattern, no obviously spoofed header — would walk straight past every gate and get the exact asset the entire project existed to protect. The beam never got swapped. Nobody was watching the door.
// Wrong: falls through to the trusted lane by default
if (highRisk) return watermarked();
if (verifiedBot) return semantic();
return clean(); // <-- reached by anyone who simply looks unremarkable
// Fixed: the trusted lane requires positive proof, nothing else does
if (validHMAC) return clean();
if (verifiedBot) return semantic();
return watermarked(); // <-- the only default
One line, reordered. The lesson underneath it isn't about SVGs — it's that the absence of a red flag is not proof of a green light. Every gate in the system now defaults to the least trusted state, and the privileged lane has to be earned, never inherited by elimination.
Here is the complete architectural flow of our Edge Function after securing the gates:
Watch the swap happen live
Three buttons, three requests, three verdicts — all against the actual endpoint, not a mockup. But a demo that just shows a different picture could still be a client-side trick. So the UI does something more honest: it intercepts the raw HTTP response headers coming back from EdgeOne — X-Content-Negotiator-State, Cache-Control, X-Edge-Execution-Time — and prints them into a terminal-style log, live, in front of you. You're not watching a picture change. You're watching the network tab, just formatted to be readable.
Click "I'm legit" and watch a signed request clear in milliseconds via crypto.subtle.verify, constant-time, no side channel to exploit. Click "I'm a search bot" and watch the JSON-LD appear in the response. Click "I'm a scraper" and watch the beam get swapped, header and all.
The 0ms - 1ms Proof: The most important header printed in that terminal is X-Edge-Execution-Time. To prove the "under 20ms" claim isn't just theory, the Edge Function measures its own execution time using Date.now() and injects it into the response. Because context.waitUntil() pushes KV Analytics into a non-blocking background task, the function reports about 1ms of on-edge compute time. End-to-end latency still depends on network distance, routing, TLS, and response transfer.
(One honest footnote from building this: EdgeOne's own edge caching is aggressive enough that repeated clicks on "Citizen" or "Merchant" during a demo were being served straight from cache — never reaching the function at all, so the analytics counter never moved. The fix was cache-busting each demo request with a timestamp parameter, explicitly removed in a real production deployment. Even the CDN doing its job too well can hide the proof you're trying to show.)
Try it yourself, and watch the counters move: www.ditogianto.web.id
The numbers, not the projections
After the first cached response, repeat requests for the same card in States 1 and 2 can be served directly from the edge without rendering again at the origin. The full source is open, MIT-licensed, running on EdgeOne right now: GitHub Repository (Backend/Worker) and GitHub Repository (Frontend/UI).
The gate, again
The Yumen Gate was never really a wall. It was a decision, made in the moment someone approached, about who they actually were.
That's what three tactics and one Edge Function do here, in under 20 milliseconds: borrow EdgeOne's own AI to meet AI bots, create real value out of what used to be nothing, and swap the beam before the theft ever completes.
Fork the code. Build your own gate. The only limit is your imagination.
Built on Tencent EdgeOne.
#TencentEdgeOne #EdgeOneMakers #CODEPOLITAN #EdgeOne








Top comments (0)