1. What Exactly Is Ladder—and Why Should You Care?
Ladder is an open-source, Go-based HTTP proxy that clones the core trick used by sites such as 1ft.io and 12ft.io: it dresses up as Googlebot, asks the target page for the “search-engine” version, strips the paywall markup, and hands you a clean article. You host it yourself, so nobody logs your reading list and no third-party limits your usage.
Who this guide is for
-
College (and above) reading level -
Zero tolerance for “marketing fluff” -
Comfortable copying commands into a terminal or Docker prompt
What you will get
-
A private proxy running on your laptop, home server, or cloud instance -
Step-by-step copy-paste blocks for Windows, macOS, Linux, Docker, Docker Compose, Helm -
A plain-English tour of every setting and YAML knob—so you can fix it when (not if) a site changes its layout
2. How the Magic Happens (The 30-Second Version)
-
Browser → Ladder (asks for article) -
Ladder → Website (pretends to be Googlebot) -
Website → Ladder (sends full HTML) -
Ladder scrubs ads, paywall scripts, and CORS headers → Browser
That’s it. No browser extension, no VPN, no account cookies.
3. Pick Your Install Style in One Table
Route | Time | When to Use |
---|---|---|
Pre-built binary | 2 min | Quick look on your own PC |
Docker one-liner | 3 min | Always-on box at home |
Docker Compose | 5 min | Keeps your config in Git |
Helm chart | 10 min | Kubernetes cluster |
All four routes are covered below—jump to the one you like.
4. Binary Install (Windows / macOS / Linux)
-
Download the latest release
-
Windows: ladder_windows_amd64.exe
-
macOS Intel: ladder_darwin_amd64
-
macOS Apple Silicon: ladder_darwin_arm64
-
Linux x86-64: ladder_linux_amd64
-
-
Make it executable (macOS/Linux)
chmod +x ladder
-
Start it
-
Windows: double-click or .\ladder.exe
-
macOS/Linux: ./ladder
-
-
Open
http://localhost:8080
Paste any article URL, press Enter.
Security heads-up
Default port 8080 is wide open and unauthenticated. If another person can reach your IP, addUSERPASS
(shown in §6) before you finish your coffee.
5. Docker One-Liner
docker run -d \
-p 8080:8080 \
-e RULESET=https://t.ly/14PSf \
--name ladder \
ghcr.io/everywall/ladder:latest
Check logs:
docker logs -f ladder
Update later:
docker pull ghcr.io/everywall/ladder:latest
docker stop ladder && docker rm ladder
# re-run the same docker run string
6. Docker Compose (Recommended for Homelabs)
Create docker-compose.yaml
:
version: "3.9"
services:
ladder:
image: ghcr.io/everywall/ladder:latest
ports:
- "8080:8080"
environment:
USERPASS: "admin:YOUR_STRONG_PASS"
RULESET: "https://raw.githubusercontent.com/everywall/ladder-rules/main/ruleset.yaml"
LOG_URLS: "true"
restart: unless-stopped
Bring it up:
docker compose up -d
Down or upgrade:
docker compose down
docker compose pull && docker compose up -d
7. Kubernetes / Helm
Add the repo:
helm repo add ladder https://everywall.github.io/ladder
helm install myladder ladder/ladder \
--set userpass=admin:YOUR_STRONG_PASS \
--set service.type=ClusterIP
See helm-chart/README.md
for Ingress TLS, persistent rules, and resource limits.
8. Configuration Dictionary (All Env Vars)
Variable | Default | Purpose | Example |
---|---|---|---|
PORT | 8080 | TCP port inside container | 8888 |
PREFORK | false | Spawn multiple workers | true |
USER_AGENT | Googlebot 2.1 | Outgoing browser signature | Mozilla/5.0 (Windows NT 10.0; Win64; x64) … |
X_FORWARDED_FOR | 66.249.66.1 | Fake crawler IP | empty = don’t send |
USERPASS | (blank) | Basic auth colon-separated | admin:StrongPass |
LOG_URLS | true | Print every fetched URL | false |
DISABLE_FORM | false | Hide the front-page URL box | true |
FORM_PATH | (blank) | Path to custom HTML form | /opt/mysite/form.html |
RULESET | official URL | YAML file or folder or URL | ./rules.yaml |
EXPOSE_RULESET | true | Let other Ladder nodes pull your rules | false |
ALLOWED_DOMAINS | (blank) | Comma list of whitelisted domains | nytimes.com,washingtonpost.com |
ALLOWED_DOMAINS_RULESET | false | Auto-allow domains found in rules | true |
Note
ALLOWED_DOMAINS
andALLOWED_DOMAINS_RULESET
are combined. If both are empty, the proxy accepts any target.
9. Quick Usage Examples
A. Browser bookmarklet
Create a bookmark with this location:
javascript:window.location.href="http://YOUR_IP:8080/"+encodeURIComponent(location.href)
Click it when you hit a paywall.
B. Raw HTML API
curl http://YOUR_IP:8080/raw/https://www.example.com/article
C. JSON-free API
curl http://YOUR_IP:8080/api/https://www.example.com/article
10. Rule Sets: Teaching Ladder New Tricks
A rule is plain YAML telling Ladder:
-
Which domains it applies to -
How to rewrite request/response headers -
Regex replacements in HTML -
Code snippets to inject
Minimal working example:
- domain: example.com
headers:
user-agent: Mozilla/5.0 (Googlebot 2.1)
regexRules:
- match: <script[^>]*src="(/[^"]*)"
replace: <script src="https://www.example.com$1"
injections:
- position: head
append: |
<script>
window.localStorage.clear();
</script>
Drop the file anywhere and point RULESET
to it, or host it on a static URL so multiple Ladder nodes can share it.
11. Anatomy of a Rule (Line-by-Line)
Section | What You Can Do |
---|---|
domain: |
Main domain (catches sub-domains) |
domains: |
Extra exact-match domains |
paths: |
Limit rule to certain URL paths |
headers: |
Add/overwrite/delete request or response headers (delete by setting value to none ) |
regexRules: |
List of match /replace pairs, applied in order |
injections: |
append , prepend , or replace HTML at CSS selector or standard positions (head , body ) |
urlMods: |
Rewrite query strings, domain, or path before fetching |
googleCache: |
Fetch from webcache.googleusercontent.com instead of live site |
12. Real-World Pattern: Removing a Soft Paywall
The following snippet is only a technical illustration; effectiveness changes whenever the publisher redesigns.
- domain: nytimes.com
headers:
referer: https://www.google.com/
regexRules:
- match: <div[^>]*class="[^"]*css-paywall[^"]*"[^>]*>.*?</div>
replace: ""
injections:
- position: head
prepend: |
<style>.css-paywall { display:none !important; }</style>
Save as nyt.yaml
, restart Ladder with:
docker run -d -p 8080:8080 -e RULESET=./nyt.yaml -v $(pwd)/nyt.yaml:/nyt.yaml ghcr.io/everywall/ladder:latest
13. Troubleshooting Checklist
Symptom | Likely Cause | Fix |
---|---|---|
Images not loading | Lazy-load data-src not converted |
Add regex rule to copy data-src to src |
502 returned | Target blocks Googlebot IP | Change USER_AGENT to desktop string, empty X_FORWARDED_FOR |
YAML parse error on start | Mixed spaces/tabs | Validate with online YAML linter |
permission denied in Docker bind mount |
Host file not readable | chmod 644 rules.yaml |
14. Updating & Rolling Back
Binary
-
Keep old binary named ladder.bak
-
Swap file, restart process
Docker
-
docker pull
newer tag -
docker stop / rm / run
-
Rollback: tag the previous image explicitly
Helm
helm upgrade myladder ladder/ladder --version x.y.z
helm rollback myladder REVISION
15. Development Setup (If You Want to Hack the Code)
Requirements
-
Go 1.20+ -
pnpm (only if you tweak the default form styling)
Clone and run:
git clone https://github.com/everywall/ladder.git
cd ladder
echo "dev" > handlers/VERSION
RULESET="./ruleset.yaml" go run cmd/main.go
Live-reload option (Air):
go install github.com/cosmtrek/air@latest
air
Change CSS classes inside form.html
? Rebuild:
pnpm install
pnpm build
16. Security & Legal Reminders (Don’t Skip)
-
Copyright still exists. Ladder is a tool; whether bypassing a particular paywall is legal depends on your jurisdiction and the site’s TOS. -
Basic auth is mandatory on any public IP. An open proxy becomes an abuse magnet—bandwidth, DMCA, worse. -
Don’t log what you don’t need. Flip LOG_URLS=false
if you want less liability surface. -
Keep the image updated. New builds occasionally patch the Go standard library or the proxy parser.
17. Quick Reference: All URLs You Need
Purpose | Path |
---|---|
Human UI | http://IP:PORT/ |
API (full processing) | http://IP:PORT/api/https://... |
Raw HTML only | http://IP:PORT/raw/https://... |
View running rules | http://IP:PORT/ruleset |
18. Frequently Asked Questions
Q1. Will it work on every site?
No. Sites that never serve the full text to search engines (hard paywalls) return blank or partial pages. A future Ladder release may retry via Google Cache.
Q2. Why are comments or images still broken?
Some media loads through JavaScript bundles that require a browser environment. Ladder fetches static HTML only; it does not execute JS.
Q3. Does Ladder store anything on disk?
Not by default. Logs go to stdout; you can redirect or disable them.
Q4. Can I chain a TOR exit node?
The feature is on the roadmap but not implemented yet.
Q5. Is there a rate limit?
Ladder itself does not throttle. Respect individual publishers’ politeness policies to avoid IP bans.
19. TL;DR for the Impatient
-
docker run -p 8080:8080 -e USERPASS=you:pass ghcr.io/everywall/ladder:latest
-
Browse to http://localhost:8080
-
Paste article URL → Enter -
Read peacefully -
When bored, open docker-compose.yaml
, add domains, volumes, env vars—tinker away.
20. Parting Thought
Tools come and go; paywalls adapt. Hosting your own proxy keeps the experiment alive without handing your reading history to a stranger. Use it wisely, patch it often, and remember that sustainable journalism deserves support. When you find yourself relying on a particular publication, consider subscribing.