Tor bridges are unlisted entry relays. The public guard set is published in the Tor consensus, which makes blocking trivial: an ISP just drops traffic to those IPs. Bridges aren't published, so they survive most blocks. Pluggable transports take it further by also disguising what Tor traffic looks like on the wire (obfs4 makes it random bytes, Snowflake makes it WebRTC, meek makes it HTTPS to a major CDN). Below is when to reach for each transport, the working torrc for all three, and how to refresh bridge lines when one gets burned.
When you actually need bridges
You need bridges when:
- The Tor consensus IPs are blocked at your network edge (corporate firewall, country-level filter, hotel Wi-Fi).
- Direct connection to
9001/tcpto the public Tor relays gets reset. - You can reach
https://www.torproject.orgonly via tricks like DNS-over-HTTPS or another VPN.
You don't need bridges when:
- Plain Tor works. Bridges add latency for no benefit.
- You're trying to hide from a country adversary that sees your traffic patterns. Bridges protect against IP-list blocks, not from a state-level adversary running deep packet inspection — for those, you also need a pluggable transport (obfs4 minimum) and likely a residential network upstream.
Pluggable transport comparison
| Transport | Looks like | Network friction | Best for |
|---|---|---|---|
| obfs4 | Random bytes, no recognizable protocol | Low latency, low CPU | Standard censorship circumvention, the default first choice |
| Snowflake | WebRTC (browser P2P video traffic) | Moderate latency, can drop mid-session | Countries with aggressive obfs4 blocking (Iran, Russia recent) — uses volunteer browsers as proxies |
| meek | HTTPS to a major CDN (Azure, Google, AWS) | High latency, expensive for the network | Last resort when obfs4 and Snowflake both blocked; uses CDN domain fronting |
| webtunnel | HTTPS to an ordinary website | Low latency, hard to distinguish from regular HTTPS | Newer transport; growing adoption since 2023 |
obfs4 is the daily-driver. Snowflake is the fallback when obfs4 IPs themselves are getting block-listed. meek is heavy and only useful when both above are dead.
Step 1: install the transports
The transports are separate binaries. On Debian/Ubuntu:
sudo apt install obfs4proxy
# Snowflake is a separate package on recent releases:
sudo apt install snowflake-clientOn macOS Homebrew:
brew install obfs4proxy
brew install snowflakeOn Fedora/RHEL:
sudo dnf install obfs4
sudo dnf install snowflake-clientAfter install, locate the binaries — you'll need their paths for ClientTransportPlugin:
which obfs4proxy
# /usr/bin/obfs4proxy
which snowflake-client
# /usr/bin/snowflake-clientStep 2: get fresh bridge lines
Three ways to get a bridge line, in increasing order of operational friction:
bridges.torproject.org (web)
Open https://bridges.torproject.org/options/ and pick a transport. The page returns three bridge lines per request. Refresh every 24 hours for a different set; the pool rotates to make bulk discovery harder.
If bridges.torproject.org is itself blocked (it often is in heavy-censorship countries), use one of the moat backends:
# Via the moat-direct backend
curl https://moat.torproject.org/circumvention/api/v1/builtinEmail to bridges@torproject.org
If web requests are blocked entirely, email a request:
- From: a Gmail, Riseup, or Outlook account (anti-abuse filter; other providers may be ignored)
- To:
bridges@torproject.org - Body:
get transport obfs4(orsnowflake,meek-azure)
You get an auto-reply within a minute or two containing fresh bridge lines.
Built-in Tor Browser bridges
Tor Browser ships with a small set of "default bridges" hardcoded for first-time users. They're widely known and increasingly blocked in heavily-censored networks, but they're a fine starting point for testing your setup. Find them in the Tor Browser's torrc-defaults file inside the bundle.
Step 3: configure torrc
The pattern is identical across transports: enable bridges, point Tor at the transport binary, paste bridge lines.
obfs4 example torrc
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
# Replace these with bridge lines from bridges.torproject.org
Bridge obfs4 192.0.2.10:443 0123456789ABCDEF0123456789ABCDEF01234567 cert=AAAA... iat-mode=0
Bridge obfs4 192.0.2.11:443 9876543210FEDCBA9876543210FEDCBA98765432 cert=BBBB... iat-mode=0
Bridge obfs4 198.51.100.5:443 ABCDEFFEDCBA0123ABCDEFFEDCBA01234567ABCD cert=CCCC... iat-mode=0Three bridges is the right number: enough redundancy for one going down, low enough not to hammer volunteer infrastructure. Don't paste twenty — pick three.
Snowflake example torrc
UseBridges 1
ClientTransportPlugin snowflake exec /usr/bin/snowflake-client
# The IP in a snowflake Bridge line is symbolic — actual traffic
# routes via WebRTC through a volunteer browser, then to the relay.
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72Snowflake also accepts an inline configuration with custom relays, but the default works. The 56-character fingerprint is the destination relay, not the WebRTC peer.
meek example torrc
UseBridges 1
ClientTransportPlugin meek_lite exec /usr/bin/obfs4proxy
# meek-azure: domain-fronts through Azure CDN. The "front" is the
# externally visible HTTPS server name; "url" is the actual meek endpoint.
Bridge meek_lite 192.0.2.2:2 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com utls=HelloRandomizedALPNmeek is the heaviest transport. Don't use it unless obfs4 and Snowflake are both failing. The Tor Project has been deprecating meek backends over time as CDN providers stop accepting domain fronting.
Mixing transports
You can include multiple transports in one torrc — Tor tries them in order:
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
ClientTransportPlugin snowflake exec /usr/bin/snowflake-client
Bridge obfs4 192.0.2.10:443 0123456789ABCDEF... cert=AAAA... iat-mode=0
Bridge obfs4 192.0.2.11:443 9876543210FEDCBA... cert=BBBB... iat-mode=0
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62...Tor falls back to Snowflake if all the obfs4 bridges are unreachable. This is the resilient setup if you're operating in a network where obfs4 occasionally gets burned but Snowflake keeps working.
Step 4: reload and verify
sudo systemctl reload tor
# or
sudo pkill -HUP tor
# Watch the logs to see which bridges connect
sudo tail -f /var/log/tor/notices.logYou're looking for lines like:
[notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits
[notice] Bootstrapped 100% (done): Done
If you see repeated failed to find Tor or cannot connect to bridge errors, your bridge lines may be burned. Get fresh ones from bridges.torproject.org and replace.
Operational tips
Don't reuse the same three bridges forever. Active censorship operations probe and block bridge IPs over weeks-to-months. Rotate every couple of months even if your current set still works.
Don't share bridge lines publicly. A bridge that ends up in a public gist gets onto block lists within days. If you want to help others, point them at bridges.torproject.org or the email backend.
Test your setup from a hostile-ish network if you can. Bridges that work fine from your home Wi-Fi might fail from a corporate or hotel network with deeper filtering. A cheap VPS in the country you're trying to circumvent is a good way to validate.
Single-onion clients can't use bridges. If you're running a single-onion hidden service (see v3 hidden service setup), the service side doesn't benefit from bridge routing — it routes through normal guards. Bridges help only the client side.
Running your own obfs4 bridge
If you want to give back, running an obfs4 bridge is straightforward and uses minimal bandwidth:
# /etc/tor/torrc (bridge-side)
BridgeRelay 1
ORPort 9001
ServerTransportPlugin obfs4 exec /usr/bin/obfs4proxy
ServerTransportListenAddr obfs4 0.0.0.0:443
ExtORPort auto
ContactInfo your-email@example.com
Nickname myobfs4bridgeAfter running for a few hours, the bridge registers with the Tor BridgeDB and starts handing out to clients. Don't be discouraged by low traffic — bridges are deliberately distributed across many users, so any single bridge sees only a fraction of the load.
FAQ
See also
- Tor Country Codes for ExitNodes, ExcludeNodes, and torify: country pinning torrc directives once your bridges are up and you can choose where the connection exits
- Host a v3 .onion Hidden Service with Tor: running a hidden service that stays reachable over a bridge connection
- Use Tor as a SOCKS5 Proxy with curl, Python, and Node: how to point applications at the SOCKS port once Tor is reaching the network
- Force a New Tor Circuit on Demand with NEWNYM: rotate circuits when a specific bridge gets blocked mid-session
- torrc Cheat Sheet: the rest of the torrc directives bridges interact with





