     [Blog](https://scrapfly.io/blog)   /  [proxies](https://scrapfly.io/blog/tag/proxies)   /  [How to Use Tor as a Proxy for Web Scraping in 2026](https://scrapfly.io/blog/posts/how-to-use-tor-for-web-scraping)   # How to Use Tor as a Proxy for Web Scraping in 2026

 by [Mazen Ramadan](https://scrapfly.io/blog/author/mazen) Apr 27, 2026 22 min read [\#proxies](https://scrapfly.io/blog/tag/proxies) [\#tools](https://scrapfly.io/blog/tag/tools) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping "Share on LinkedIn")    

 

 

   

   **Web Scraping API — Proxy Rotation**Rotate proxies from datacenter or residential pools of 130M+ proxies from 120+ countries.

 

 [ Learn More  ](https://scrapfly.io/products/web-scraping-api#features) [  Docs ](https://scrapfly.io/docs/scrape-api/getting-started#features) 

 

 

Paid proxy services work well, but the monthly bill climbs quickly once a scraping job grows past a few thousand requests per day. Tor ships the same core feature, a pool of rotating exit IPs, for free, and Tor has been battle-tested by researchers and journalists for over two decades. The trade-off is speed and a smaller, publicly known IP pool, so Tor is best suited to small and medium workloads where cost matters more than throughput.

The guide covers installing Tor as a background service, configuring the SOCKS5 and HTTP proxies, rotating exit IPs programmatically with the [stem](https://stem.torproject.org/) library, tuning `torrc` for faster circuit turnover, scaling with multiple Tor instances, and the limitations that decide when to upgrade to paid infrastructure.

## Key Takeaways

- Tor gives scrapers a free SOCKS5 and HTTP proxy on localhost by routing traffic through three encrypted relay hops, and the Python stem library turns a single Tor process into a programmable rotating proxy by requesting a new circuit between requests.
- Install Tor as a system daemon (apt, brew, or the Windows service) so scraping scripts run headlessly without depending on the Tor Browser. The daemon exposes the same SOCKS5 port (9050) the browser uses.
- Route requests and DNS through the Tor network in a single step by connecting through socks5h://127.0.0.1:9050. The h suffix prevents the local resolver from seeing scraping targets.
- Rotate exit IPs programmatically by opening Tor's Control Port (9051) and sending the NEWNYM signal via stem. Tor enforces a ~10-second cooldown between rotations, so a single instance caps at roughly six new circuits per minute.
- Tune MaxCircuitDirtiness in torrc to force-rotate circuits on a timer, and run multiple Tor instances on separate port pairs when one circuit's cooldown is not enough throughput.
- Tor's ~1,500 exit IPs are publicly listed and proactively blocked by Cloudflare, DataDome, and most anti-bot systems, so Tor is practical for learning and small-scale jobs but not for protected production targets.
- For scraping that outgrows Tor's speed and IP pool, [Scrapfly](https://scrapfly.io/products/web-scraping-api) handles proxy rotation across 130M+ residential and datacenter IPs, anti-bot bypass, and JavaScript rendering behind a single HTTP call.

**Get web scraping tips in your inbox**Trusted by 100K+ developers and 30K+ enterprises. Unsubscribe anytime.







## What is Tor?

[Tor](https://www.torproject.org/) (The Onion Router) is a free, open-source privacy network that routes internet traffic through a worldwide volunteer network of relays. Tor is most commonly used through the Tor Browser, a hardened Firefox build, but the same network is available to any application that can speak SOCKS5.

From a web scraping perspective, Tor provides several useful properties:

- **Different IP address on every circuit**, sourced from Tor's pool of volunteer exit relays.
- **Blocks third-party trackers** by clearing cookies and browsing state between sessions.
- **Prevents connection monitoring**, so an observer between the client and the entry node cannot see the destination.
- **Resists fingerprinting** because the Tor Browser standardizes many browser attributes across users.
- **Reaches `.onion` hidden services** that are unreachable over the normal DNS system.

Although Tor was designed for human browsing, Tor's SOCKS5 interface makes the same relay network available to HTTP clients, headless browsers, and custom scrapers.



## How Does Tor Work?

Tor traffic travels through three relays before reaching the destination, and Tor encrypts each hop in a separate layer (the onion metaphor). The three relays are called the **entry node**, **middle node**, and **exit node**, and Tor picks a fresh set of three nodes to form each new circuit.

The three relays and the information each relay sees:

- **Entry node** The entry node knows the real client IP but cannot see the final destination. The entry node peels off the outer encryption layer and forwards the packet inward.
- **Middle node** The middle node sees neither the client nor the destination. The middle node's only job is to hop the packet one step further along the circuit.
- **Exit node** The exit node removes the last encryption layer and sends the request to the destination server. The exit node sees the destination but does not know who originated the request.

The destination server only ever sees the exit node's IP address, which is how Tor turns into a free proxy pool for web scraping.



## How to Install Tor for Web Scraping?

Tor can be installed either as a desktop browser or as a background service, and for web scraping the background service is strongly preferred because the background service does not require keeping a browser window open. Tor's background service exposes the same SOCKS5 interface on port 9050 that the Tor Browser uses.

The two installation paths are covered below, starting with the browser (simpler but heavier) and then the background service.

### How to Install Tor Browser?

The simplest way to try Tor is the Tor Browser, which ships Tor bundled with a hardened Firefox build. Download the installer from the [official Tor Project download page](https://www.torproject.org/download/) and pick the build for the target operating system.

After installing Tor Browser, run the Tor Browser executable and click **Connect**. The Tor Browser then opens on the new-tab page that confirms the connection:

The Tor Browser path works for experimentation, but the Tor Browser has a cost for scraping: the browser must stay open for any external client to use port 9050. A scraping script that starts at 3am on a headless server cannot rely on a user-facing browser, so the background service path below is the better default for scraping workloads.

### How to Install Tor as a Background Service?

Installing Tor as a background service also called the Tor daemon puts Tor under the system's service manager, so Tor starts on boot and runs without a visible window. Every major operating system ships a Tor package in its default package manager.

bash```bash
# Debian, Ubuntu, and derivatives
sudo apt update
sudo apt install tor
sudo systemctl enable --now tor

# Verify the SOCKS5 port is listening on 9050
sudo ss -tnlp | grep 9050

# macOS with Homebrew
brew install tor
brew services start tor

# Verify the SOCKS5 port is listening on 9050
lsof -iTCP:9050 -sTCP:LISTEN
```



The commands above install the Tor daemon, register the daemon with the system service manager, and confirm that Tor is accepting SOCKS5 connections on `127.0.0.1:9050`. The Tor daemon listens on the same port as the Tor Browser by default, so client code does not change when switching from the browser to the daemon.

Once Tor is running as a service, the `torrc` configuration file lives at `/etc/tor/torrc` on Linux, `$(brew --prefix)/etc/tor/torrc` on macOS, and next to `tor.exe` on Windows. Every configuration change mentioned later in this guide goes into the `torrc` file, and Tor picks up the changes after a restart `sudo systemctl restart tor` on Linux, `brew services restart tor` on macOS.



## How to Use Tor as a Proxy Server for Web Scraping?

Tor can serve as both a SOCKS5 and an HTTP proxy, and either one routes scraping traffic through the three-hop Tor circuit so the destination site sees the exit node IP. The SOCKS5 interface is enabled by default on port 9050, while the HTTP interface needs one extra line in `torrc` to be available on port 9080.

The two sections below cover each interface with a minimal `httpx` example, and the same proxy URLs work with any client that speaks the matching protocol.

### How to Connect Through Tor's SOCKS5 Proxy?

Tor's SOCKS5 proxy is the native way to send traffic through the Tor network, and the proxy accepts connections at `127.0.0.1:9050` out of the box with no configuration. Install the SOCKS extra for [httpx](https://www.python-httpx.org/) first, because SOCKS support is an optional dependency:

bash```bash
pip install "httpx[socks]"
```



The command above pulls in the `socksio` package that `httpx` needs to speak SOCKS5. The same extra is available for `requests` as `pip install "requests[socks]"`, and both libraries then accept `socks5://` and `socks5h://` proxy URLs.

python```python
import httpx

# socks5h:// resolves DNS on the Tor exit node, not on the local resolver
client = httpx.Client(proxy="socks5h://127.0.0.1:9050")

response = client.get("https://httpbin.dev/ip")
print(response.json())
# {'origin': '185.243.218.61'}
```



The script above creates an httpx client that routes every request through Tor's SOCKS5 port. The socks5h:// scheme is important: the h suffix tells the proxy to resolve DNS on the Tor exit node, not on the local machine. Using plain socks5:// leaks every target domain to the local resolver, so socks5h:// is the safer default for scraping.

The same SOCKS5 endpoint works with other common HTTP clients; the linked answer pages walk through the setup for each:

- [Using a Tor proxy with cURL](https://scrapfly.io/blog/answers/how-to-use-proxy-with-curl) covers the `--socks5-hostname` flag and environment variables.
- [Python requests proxy setup](https://scrapfly.io/blog/answers/python-requests-proxy-intro) covers per-request overrides and session-level defaults.
- [A focused primer on SOCKS5 proxies](https://scrapfly.io/blog/answers/what-are-socks5-proxies-in-web-scraping) explains the protocol itself.

### How to Enable Tor's HTTP Tunnel Proxy?

Tor also supports a plain HTTP proxy interface, which is useful for tools and libraries that cannot speak SOCKS5. The HTTP interface is disabled by default, so the first step is adding a single line to the `torrc` file.

Open the `torrc` file (path depends on the operating system; see the previous section) and add:

ini```ini
HTTPTunnelPort 9080
```



The directive above tells Tor to listen for HTTP proxy connections on port 9080 in addition to the SOCKS5 port. Save the file and restart Tor so the change takes effect (`sudo systemctl restart tor` on Linux, `brew services restart tor` on macOS).

With the HTTP tunnel enabled, the same scraping code that used a SOCKS5 URL can use an `http://` URL instead:

python```python
import httpx

client = httpx.Client(proxy="http://127.0.0.1:9080")

response = client.get("https://httpbin.dev/ip")
print(response.json())
# {'origin': '104.244.72.115'}
```



The script above reuses the standard `httpx` proxy argument with the HTTP tunnel URL, and the rest of the code is identical to any other HTTP proxy setup. The HTTP tunnel is convenient for headless browsers such as [Web Scraping with Selenium and Python](https://scrapfly.io/blog/posts/web-scraping-with-selenium-and-python), [Web Scraping with Playwright and Python](https://scrapfly.io/blog/posts/web-scraping-with-playwright-and-python), and [How to Web Scrape with Puppeteer and NodeJS in 2026](https://scrapfly.io/blog/posts/web-scraping-with-puppeteer-and-nodejs), which accept HTTP proxies more readily than SOCKS5 proxies.

The protocol-level differences between the two Tor interfaces (caching, DNS, header behavior) mirror the general HTTP vs SOCKS5 comparison, so the guide is a useful companion for picking between the two.

[SOCKS5 vs HTTP Proxy: Key Differences and When to Use EachA deep dive into the key differences between HTTPS and SOCKS proxies, helping you choose the right protocol for your web scraping needs.](https://scrapfly.io/blog/posts/https-vs-socks-proxies)



## How to Rotate IPs Programmatically With Tor?

Tor assigns a new exit IP whenever the client requests a new circuit through the Control Port, and the Python `stem` library lets scraping code do exactly that by sending a `NEWNYM` signal. A single Tor process can cycle through hundreds of different exit IPs in a scraping session, as long as the code respects the minimum cooldown between rotations.

The sub-sections below explain how Tor's Control Port works, walk through a complete rotation script, and cover the two `torrc` options that control automatic circuit turnover.

### How Does IP Rotation Work With Tor's Control Port?

Tor exposes two separate ports: the SOCKS port (9050) carries scraping traffic, while the Control Port (9051) lets an external program manage the Tor process. Sending the `NEWNYM` signal over the Control Port tells Tor to retire the current circuits and build a fresh set, which means the next request goes out through a new entry-middle-exit path and, critically, a new exit IP.

Tor enforces a minimum delay between consecutive `NEWNYM` requests, currently around ten seconds, to protect the network from circuit churn. The `stem` library exposes the remaining cooldown as `controller.get_newnym_wait()`, so a polite scraper can check the delay before asking for a rotation instead of guessing.

Before writing any code, the Control Port has to be enabled in `torrc`, alongside one authentication method. Cookie authentication is the simplest for a single-host setup because the cookie is a file Tor writes at startup, and the Tor process and the scraper run under the same user account.

ini```ini
ControlPort 9051
CookieAuthentication 1
```



The snippet above enables the Control Port on localhost and turns on cookie-based authentication. Save the file and restart Tor (`sudo systemctl restart tor`) so the Control Port starts listening.

### How to Implement Tor IP Rotation in Python?

With the Control Port enabled, the rotation loop is a handful of lines: open a controller, authenticate, send `NEWNYM`, wait out the cooldown, and continue scraping through the SOCKS5 proxy. Install the two libraries the script below needs:

bash```bash
pip install stem "httpx[socks]"
```



The command above pulls in `stem` (Tor's official Python controller) and `httpx` with SOCKS support. Both libraries work on Linux, macOS, and Windows.

python```python
import time
import httpx
from stem import Signal
from stem.control import Controller

TOR_SOCKS_URL = "socks5h://127.0.0.1:9050"

def renew_tor_circuit():
    """Ask Tor for a new circuit so the next request uses a different exit IP."""
    with Controller.from_port(port=9051) as controller:
        controller.authenticate()  # uses cookie auth by default
        wait = controller.get_newnym_wait()
        if wait > 0:
            time.sleep(wait)
        controller.signal(Signal.NEWNYM)

def scrape_with_rotation(urls):
    for url in urls:
        with httpx.Client(proxy=TOR_SOCKS_URL, timeout=30) as client:
            ip = client.get("https://httpbin.dev/ip").json()["origin"]
            page = client.get(url)
            print(f"Scraped {url} via exit IP {ip}: {page.status_code}")
        renew_tor_circuit()

if __name__ == "__main__":
    targets = [
        "https://web-scraping.dev/products?page=1",
        "https://web-scraping.dev/products?page=2",
        "https://web-scraping.dev/products?page=3",
    ]
    scrape_with_rotation(targets)
```



The script above scrapes three pages, each through a fresh Tor circuit. The `renew_tor_circuit` function opens a short-lived connection to the Control Port, asks Tor how much of the NEWNYM cooldown is left, waits out the remainder, and then sends the rotation signal. The scraping loop uses the standard `httpx` SOCKS5 client from the previous section, so the rotation logic is additive on top of the proxy setup.

Two practical notes on the script above:

- The `httpbin.dev/ip` call is only there to confirm the IP changed between iterations; production code should skip the IP check to save a round trip.
- The ten second cooldown is the floor on rotation frequency for a single Tor instance, so a single-instance setup caps throughput at roughly six requests per minute per circuit, not counting the scraping request itself.

### How to Tune torrc for Faster Rotation?

Two `torrc` options control how aggressively Tor rotates circuits on its own, independently of any `NEWNYM` signal. Both options live in the same file that already hosts `HTTPTunnelPort` and `ControlPort`:

ini```ini
# Build a new circuit at most every 30 seconds under normal conditions
NewCircuitPeriod 30

# Force-rotate any circuit older than 60 seconds
MaxCircuitDirtiness 60
```



The config above tells Tor to consider building a new circuit every 30 seconds and to discard any circuit once the circuit is 60 seconds old, whichever comes first. The defaults are 30 seconds and 10 minutes respectively, so lowering `MaxCircuitDirtiness` is the knob that most directly increases IP churn for a long-running scraper.

Both values trade network load against rotation speed. Setting either value below ten seconds strains Tor's directory services and is considered impolite to the volunteer network, so treat ten seconds as a practical lower bound.

For more rotation patterns that apply to any proxy backend (not just Tor), the dedicated rotation guide covers distribution strategies, subnet awareness, and weighted selection:

[How to Rotate Proxies in Web ScrapingIn this article we explore proxy rotation. How does it affect web scraping success and blocking rates and how can we smartly distribute our traffic through a pool of proxies for the best results.](https://scrapfly.io/blog/posts/how-to-rotate-proxies-in-web-scraping)



## How to Scale Tor Scraping With Multiple Instances?

A single Tor instance provides one exit IP at a time with a ten second cooldown between rotations, which caps throughput at roughly six new circuits per minute. To scrape faster, the standard pattern is to run several Tor instances side by side, each with its own SOCKS and Control ports, and then round-robin scraping traffic across the instances.

Each instance gets a unique pair of ports, a separate data directory, and optionally a separate `torrc` file. A minimal three-instance layout looks like this:

ini```ini
# tor1.conf
SocksPort 9050
ControlPort 9051
DataDirectory /var/lib/tor1
CookieAuthFile /var/lib/tor1/control_auth_cookie

# tor2.conf
SocksPort 9052
ControlPort 9053
DataDirectory /var/lib/tor2
CookieAuthFile /var/lib/tor2/control_auth_cookie

# tor3.conf
SocksPort 9054
ControlPort 9055
DataDirectory /var/lib/tor3
CookieAuthFile /var/lib/tor3/control_auth_cookie
```



The config above defines three independent Tor processes on ports 9050/9051, 9052/9053, and 9054/9055. Launch each instance with `tor -f tor1.conf`, and the scraping code can then pick a SOCKS port at random (or round-robin) for every request, tripling the effective rotation rate.

Running multiple instances by hand gets tedious quickly, so the community has published Docker images that handle the orchestration:

- [rotating-tor-http-proxy](https://github.com/zhaow-de/rotating-tor-http-proxy) runs several Tor processes inside a single container and exposes one HTTP endpoint backed by HAProxy, so the scraper only talks to one address.
- [docker-multi-tor](https://github.com/y4ns0l0/docker-multi-tor) is a lighter Alpine-based image that wraps Tor and Polipo for teams that want more direct control over each instance.

Both images are worth looking at as reference implementations even if the final deployment is a custom `docker-compose.yml`.

Tor's exit node pool is roughly 1,500 to 2,000 IPs at any moment, shared by every Tor user on the planet. Running more than ten or twenty instances quickly hits diminishing returns, because the new instances draw from the same small pool and the overlap grows with each additional process.



Scrapfly

#### Scale your web scraping effortlessly

Scrapfly handles proxies, browsers, and anti-bot bypass — so you can focus on data.

[Try Free →](https://scrapfly.io/register)## What Are the Limitations of Web Scraping With Tor?

Tor provides free IP rotation but comes with three structural trade-offs: slower requests, a small and publicly known exit node pool, and high blocking rates from anti-bot systems that recognize Tor IPs. None of these trade-offs is a deal-breaker for small or medium scraping jobs, but each one becomes painful as the scraping volume grows.

The three limitations, in the order they usually bite:

- **Latency is 2 to 5 times higher than a direct connection.** Every request traverses three encrypted hops across volunteer servers, and each hop adds handshake and transport overhead. A request that takes 300ms direct often takes 1 to 2 seconds through Tor, and tail latencies are worse.
- **The exit node pool is small and public.** The Tor Project publishes the exit list in real time at [check.torproject.org](https://check.torproject.org/exit-addresses), so anti-bot systems like Cloudflare, DataDome, and PerimeterX can (and do) blocklist every Tor IP proactively. A site that blocks Tor blocks every single Tor user at once.
- **IP reputation is low by construction.** Tor exit IPs are shared across every Tor user on Earth, including abusive ones, so the IPs accumulate negative reputation in fraud scores, CAPTCHA thresholds, and rate limit triggers. A fresh residential IP lands on a site with a clean slate; a Tor exit rarely does.

A short benchmark makes the latency cost concrete:

python```python
import time
import httpx

def timed(label, client):
    start = time.time()
    for page in range(1, 6):
        client.get(f"https://web-scraping.dev/products?page={page}")
    print(f"{label}: {time.time() - start:.2f}s")

with httpx.Client(proxy="socks5h://127.0.0.1:9050", timeout=30) as tor_client:
    timed("Tor SOCKS5", tor_client)

with httpx.Client(timeout=30) as direct_client:
    timed("Direct", direct_client)

# Tor SOCKS5: 19.93s
# Direct: 10.36s
```



The script above fetches five pages through Tor and five pages directly, then prints the wall-clock time for each. In a typical run, the Tor version takes roughly twice as long, and the gap widens on sites with heavier pages or stricter anti-bot challenges.

Taken together, the three limitations explain why Tor sits in a specific slot in the proxy landscape. The table below compares Tor against the two paid alternatives most scraping teams use in production:

| Factor | Tor | Residential Proxies | Datacenter Proxies |
|---|---|---|---|
| Cost | Free | High | Low |
| Speed | Slow (2 to 5x latency) | Fast | Fast |
| IP pool size | ~1,500 exit nodes | Millions | Thousands to millions |
| Geo-targeting | None | Country and city level | Country level |
| Anti-bot detection | High (IPs are public) | Low | Medium |
| Best fit | Learning, small scale | Production scraping | Non-protected targets |

The table above makes the role of each proxy type explicit: Tor competes on price, residential proxies compete on realism, and datacenter proxies compete on raw throughput. For a broader survey of the options and how each proxy type holds up against anti-bot systems, the introductory guide covers the full landscape:

[The Complete Guide To Using Proxies For Web ScrapingIntroduction to proxy usage in web scraping. What types of proxies are there? How to evaluate proxy providers and avoid common issues.](https://scrapfly.io/blog/posts/introduction-to-proxies-in-web-scraping)

[How to Hide Your IP AddressIn this article we'll be taking a look at several ways to hide IP addresses: proxies, tor networks, vpns and other techniques.](https://scrapfly.io/blog/posts/how-to-hide-your-ip-address-while-scraping)



## How Does ScrapFly Handle Proxy Rotation?

For teams that outgrow Tor's speed and IP pool, Scrapfly provides a managed proxy and anti-bot layer that keeps the same "one HTTP request per scraped page" developer experience. Scrapfly handles the rotation, retries, header shaping, and anti-bot challenges behind a single API call, so scraping code does not have to manage Control Ports or circuit cooldowns.



   Scrapfly Web Scraping APIScrapFly's [Web Scraping API](https://scrapfly.io/web-scraping-api) is a single HTTP endpoint for collecting web data at scale, with a **99.99% success rate** across **130M+ proxies in 120+ countries**.

- [Anti-Scraping Protection bypass](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) - automatically defeats Cloudflare, DataDome, PerimeterX, Akamai, and 90+ other bot systems.
- [Smart proxy rotation](https://scrapfly.io/docs/scrape-api/proxy) - residential and datacenter pools with country and ASN level geo-targeting.
- [JavaScript rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering) - render SPAs and dynamic pages through real cloud browsers.
- [Browser automation scenarios](https://scrapfly.io/docs/scrape-api/javascript-scenario) - scroll, click, fill forms, and wait for elements without managing a browser fleet.
- [Format conversion](https://scrapfly.io/docs/scrape-api/getting-started#api_param_format) - return pages as HTML, JSON, clean text, or LLM ready Markdown.
- [Session management](https://scrapfly.io/docs/scrape-api/session) - keep cookies, headers, and IPs consistent across multi step flows.
- [Smart caching](https://scrapfly.io/docs/scrape-api/getting-started#api_param_cache) - cache successful responses to cut cost on repeat scraping jobs.
- [Python](https://scrapfly.io/docs/sdk/python), [TypeScript](https://scrapfly.io/docs/sdk/typescript), [Scrapy](https://scrapfly.io/docs/sdk/scrapy), and [no-code integrations](https://scrapfly.io/docs/integration/getting-started) including Make, n8n, Zapier, LangChain, and LlamaIndex.



A minimal Scrapfly call that routes through a residential proxy pool, picks the exit country, and runs the anti-scraping protection bypass looks like this:

python```python
from scrapfly import ScrapeConfig, ScrapflyClient

scrapfly = ScrapflyClient(key="Your ScrapFly API key")

response = scrapfly.scrape(ScrapeConfig(
    url="https://web-scraping.dev/products",
    asp=True,  # enable the anti scraping protection bypass
    proxy_pool="public_residential_pool",  # pick the residential pool
    country="US",  # set the exit country
    render_js=True,  # render JavaScript when the target needs it
))

# Parsel-compatible selector for quick extraction
selector = response.selector
html = response.scrape_result["content"]
```



The example above sends one request to Scrapfly's API and receives the fully rendered page back, with proxy rotation, anti-bot bypass, and optional JavaScript rendering handled on Scrapfly's side. The `proxy_pool` parameter swaps between datacenter and residential pools, and the `country` parameter selects the exit geography without any extra configuration on the client side.

### Power your scraping with Scrapfly

Forget about getting blocked. Scrapfly handles anti-bot bypasses, browser rendering, and proxy rotation so you can focus on the data.



[Try for FREE!](https://scrapfly.io/register)





## FAQ

Is using Tor for web scraping legal?Tor itself is legal in most countries, including the United States and the European Union. The legality of web scraping depends on the target website's terms of service, on copyright and database rights, and on local laws such as the Computer Fraud and Abuse Act or the GDPR, and none of those laws care whether the scraper uses Tor, a paid proxy, or a direct connection. Using Tor does not make legal scraping illegal, and Tor does not make illegal scraping legal.







Can websites detect and block Tor exit nodes?Yes, and many websites do. The Tor Project publishes the current list of exit node IPs at `check.torproject.org/exit-addresses`, and anti-bot services such as Cloudflare, DataDome, and Akamai consume the exit list and block requests from Tor IPs outright or route the requests to aggressive CAPTCHA challenges. Detectability is the single biggest reason Tor does not scale to protected production scraping targets.







Can I use Tor with Selenium or Playwright for web scraping?Yes. For Playwright, pass the Tor proxy in the browser launch options (for example, `proxy={"server": "socks5://127.0.0.1:9050"}`). For Selenium, configure the SOCKS proxy on the browser profile with Chrome's `--proxy-server=socks5://127.0.0.1:9050` flag or the equivalent Firefox preferences. Both setups work against the Tor daemon as well as the Tor Browser, because the two share the same SOCKS5 port.







How does Tor compare to residential proxies for web scraping?Tor is free but slow (2–5× latency), limited to ~1,500 publicly listed exit IPs, and blocked by most anti-bot systems. Residential proxies cost more but offer millions of IPs, fast speeds, geo-targeting, and low detection rates. Use Tor for learning and small-scale jobs; switch to residential proxies for production.









## Conclusion

This guide walked through the full progression of using Tor for web scraping: installing Tor as a background service instead of a browser, configuring the SOCKS5 and HTTP proxy interfaces, rotating exit IPs programmatically with `stem` and the `NEWNYM` signal, tuning `torrc` for faster circuit turnover, and scaling out with multiple Tor instances.

Tor is not a silver bullet. The slow latency, public exit list, and low IP reputation make Tor a poor fit for large-scale scraping of heavily protected targets, and the right response to those limits is to graduate to residential or mobile proxies.



 

    Table of Contents- [Key Takeaways](#key-takeaways)
- [What is Tor?](#what-is-tor)
- [How Does Tor Work?](#how-does-tor-work)
- [How to Install Tor for Web Scraping?](#how-to-install-tor-for-web-scraping)
- [How to Install Tor Browser?](#how-to-install-tor-browser)
- [How to Install Tor as a Background Service?](#how-to-install-tor-as-a-background-service)
- [How to Use Tor as a Proxy Server for Web Scraping?](#how-to-use-tor-as-a-proxy-server-for-web-scraping)
- [How to Connect Through Tor's SOCKS5 Proxy?](#how-to-connect-through-tor-s-socks5-proxy)
- [How to Enable Tor's HTTP Tunnel Proxy?](#how-to-enable-tor-s-http-tunnel-proxy)
- [How to Rotate IPs Programmatically With Tor?](#how-to-rotate-ips-programmatically-with-tor)
- [How Does IP Rotation Work With Tor's Control Port?](#how-does-ip-rotation-work-with-tor-s-control-port)
- [How to Implement Tor IP Rotation in Python?](#how-to-implement-tor-ip-rotation-in-python)
- [How to Tune torrc for Faster Rotation?](#how-to-tune-torrc-for-faster-rotation)
- [How to Scale Tor Scraping With Multiple Instances?](#how-to-scale-tor-scraping-with-multiple-instances)
- [What Are the Limitations of Web Scraping With Tor?](#what-are-the-limitations-of-web-scraping-with-tor)
- [How Does ScrapFly Handle Proxy Rotation?](#how-does-scrapfly-handle-proxy-rotation)
- [Power your scraping with Scrapfly](#power-your-scraping-with-scrapfly)
- [FAQ](#faq)
- [Conclusion](#conclusion)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

## Explore this Article with AI

 [ ChatGPT ](https://chat.openai.com/?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping) [ Gemini ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping) [ Grok ](https://x.com/i/grok?text=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping) [ Perplexity ](https://www.perplexity.ai/search/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping) [ Claude ](https://claude.ai/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-use-tor-for-web-scraping) 



 ## Related Articles

 [  

 blocking proxies 

### How to Hide Your IP Address

In this article we'll be taking a look at several ways to hide IP addresses: proxies, tor networks, vpns and other techn...

 

 ](https://scrapfly.io/blog/posts/how-to-hide-your-ip-address-while-scraping) [  

 http python 

### Web Scraping with Python

Introduction tutorial to web scraping with Python. How to collect and parse public data. Challenges, best practices and ...

 

 ](https://scrapfly.io/blog/posts/web-scraping-with-python) [  

 python 

### Everything to Know to Start Web Scraping in Python Today

Complete introduction to web scraping using Python: http, parsing, AI, scaling and deployment.

 

 ](https://scrapfly.io/blog/posts/everything-to-know-about-web-scraping-python) 

  



   



 Premium rotating proxies for scraping, **1,000 free credits** [Start Free](https://scrapfly.io/register)