Tor's circuit path selection algorithm balances anonymity with performance by choosing relays based on bandwidth, stability, and geographic diversity. Understanding how Tor selects the three-hop path from your client through guard, middle, and exit relays helps you configure your setup for optimal speed without sacrificing the privacy properties that make Tor valuable. This guide explains the mechanics of Tor's path selection, the factors that influence circuit quality, and the configuration parameters you can tune to improve throughput and reduce latency for your specific use case.
Need this done for your project?
We implement, you ship. Async, documented, done in days.
Tor builds three-hop circuits by selecting relays from its consensus document, a signed list updated every hour by directory authorities. The selection process weights relays by their advertised bandwidth, giving faster relays higher probability of selection. Guard relays form a special category - your Tor client selects a small set of guard relays and uses them persistently for months, rotating only when a guard becomes unavailable. This guard persistence protects against certain traffic analysis attacks by reducing the number of relays that observe your entry traffic over time. Middle relays fill the second hop and are selected fresh for each circuit. Exit relays handle the final hop and are filtered by exit policy to match your destination port.
Bandwidth Weights and Relay Capacity
The consensus assigns bandwidth weights to each relay position (guard, middle, exit) based on the relay's measured and advertised capacity relative to the total network capacity. When you configure a relay with BandwidthRate and BandwidthBurst, the bandwidth authorities measure actual throughput and assign a weight accordingly. For circuit users, this means high-capacity relays in well-connected data centers carry more traffic. Hosting your relay in a facility with direct peering to major backbone providers improves the bandwidth authority measurements, increasing your weight and traffic volume. Guard relays specifically benefit from consistent uptime - relays in the Guard position that maintain 95%+ uptime over 2+ months receive the Guard flag, making them eligible for persistent selection.
Tuning NumEntryGuards and Circuit Periods
The NumEntryGuards option (default 1 in modern Tor) controls how many guard relays your client maintains. Increasing to 2 or 3 provides resilience if a guard goes offline, at the cost of exposing your entry traffic to more relays over time. The NewCircuitPeriod option (default 30 seconds) controls how often Tor considers building new circuits. For latency-sensitive applications, reducing this to 10-15 seconds allows faster recovery from poor circuit paths, though it increases circuit churn and reduces the persistence that guards are designed to provide.
Exit Node Selection and Port Policies
Exit selection is the most constraining part of circuit building because exits must match your destination port. Only about 1,000 of Tor's 7,000+ relays carry the Exit flag, and many have restrictive port policies. When your destination requires an uncommon port, Tor may struggle to find suitable exits, extending circuit build time. The ExitNodes option lets you specify preferred exit countries using ISO codes (ExitNodes {us},{de},{nl}), which can reduce latency to specific destinations. However, overly restricting exit geography reduces the candidate pool and can hurt anonymity by making your circuits predictable.
Circuit Build Timeout and Preemptive Building
CircuitBuildTimeout (default 60 seconds) determines how long Tor waits for a circuit to complete before discarding it and trying again. For responsive applications, reducing this to 15-20 seconds causes Tor to abandon slow circuits faster. LearnCircuitBuildTimeout (default 1, enabled) lets Tor adaptively learn the optimal timeout based on historical circuit build times. NumPrebuiltCircuits (default 10) controls how many circuits Tor speculatively builds before they are needed. Increasing this to 20-30 for high-traffic scenarios ensures circuits are ready when connections arrive. The MaxCircuitDirtiness option (default 600 seconds) controls how long a circuit remains eligible for new streams.