Mission
Make abusive scraping costly and pointless, and protect the content creators have made.
Open-source scraper defence
BotLocker is a reverse proxy that spots scrapers and lures them into an endless maze of generated pages. They burn their own time and bandwidth, while your real content and your real visitors are never touched.
Manifest
Bots take what we publish without consent, without credit, and without compensation. They burn bandwidth, inflate costs, and degrade the experience for the people we build for. We are tired of it, so BotLocker makes abusive scraping expensive and pointless.
Make abusive scraping costly and pointless, and protect the content creators have made.
Our content is ours to offer, not to take.
We only waste the time of bots that ignore our rules. We never attack third parties.
A misclassified visitor always has a way out, and is never served anything harmful.
Small, understandable parts beat clever ones.
We honour robots.txt and document what we do, in plain words.
How it works
BotLocker sits in front of your site. Each request is classified before it reaches your origin.
Search engines and other allowlisted good bots pass straight through.
A request under the maze path is always trapped. No human reaches it.
Weak signals add up: headers, user agent, behaviour, network, and more.
Low scores pass. Mid scores get a challenge. High scores from two or more signal families go to the maze.
Each maze page is generated from a keyed hash of its path, so the same path always gives the same
page and nothing has to be stored. Every page is filler text with links deeper into the maze, so it
never ends. Maze pages are marked noindex, and robots.txt disallows the path
so compliant crawlers never enter it.
Clients that don't run the page never get a pass.
Detection
No single signal is trusted alone. A score crosses a threshold only when several independent signal families agree. That keeps one noisy check from trapping a real person.
Missing Accept-Language or Accept, and Chrome user agents without fetch metadata.
User agents from common scraping libraries, and empty user agents.
Request rate per window, and many page views with no CSS, JS, or image loads.
A link no human sees. Any request to the maze path is a trap, with no score needed.
WebDriver automation, headless Chrome, and zero-size windows, reported from the challenge page.
Hosting ASNs and TLS fingerprints. These need a data source, so they stay silent until you add one.
Score at or above trap_at (default 6.0) from two or more families means the maze. Score at or above challenge_at (default 3.0) means a challenge. Below that, the visitor passes.
Dashboard
A local dashboard shows every connection, every captured bot, and why it was captured. It also lets you change settings, and the proxy reloads within seconds.
Sample data
Every captured client, with the rule that caught it and its evidence.
The most recent decisions, with the action and the reason for each.
Edit thresholds and limits. Each save is validated, audited, and applied without a restart.
Deploy
Both run the same Rust detection core, so the rules are identical.
A single Rust binary that proxies your site and serves the dashboard on loopback.
cd backend
cargo build --release -p botlocker
cp botlocker.example.toml botlocker.toml
export BOTLOCKER_SECRET="$(openssl rand -hex 32)"
./target/release/botlocker --config botlocker.toml
An nginx build with the module compiled in, started with Compose. The dashboard is optional.
cd nginx
cp .env.example .env # set ORIGIN_URL
mkdir -p secrets && openssl rand -hex 32 > secrets/botlocker_secret
docker compose -f docker-compose-nginx.yaml up -d --build
Put your robots.txt in nginx/robots/ to serve it, and keep the Disallow: /maze/ line.
Honest limits
BotLocker raises the cost of scraping. It does not promise perfect detection.
A browser that hides automation, or a headless one with realistic fingerprints, can pass the browser report.
The challenge report comes from the browser, so a client can send one without running the page. It raises the cost but doesn't prove a real browser.
Visitors behind one NAT or CDN share a rate limit and a pass. Real client IP handling behind a load balancer is not built yet.
ASN and TLS fingerprint signals need a data source. The nginx build has no ASN or fingerprint data.
Your content is yours to offer. BotLocker makes taking it without asking a bad deal.