# How BitChat Implements Tor Integration to Enhance User Privacy

> Discover how BitChat uses Tor integration with Arti, the official iOS Tor library, to route all network traffic and bolster user privacy via a local SOCKS5 proxy.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-08-07

---

**BitChat routes all network traffic through the Tor network using Arti, the official Tor library for iOS, which runs as an embedded daemon and exposes a local SOCKS5 proxy for all outbound connections.**

Privacy-focused messaging demands more than end-to-end encryption—it requires network-level anonymity. The **BitChat** iOS app achieves this by integrating the **Tor** anonymity network directly into its codebase. Unlike VPN-based solutions that route traffic through centralized servers, BitChat's **Tor integration** creates a self-contained circuit that obfuscates the user's IP address and location from both network observers and service operators.

## Arti: The Official iOS Tor Library

BitChat's **Tor implementation** relies on **Arti**, the Rust-based Tor client maintained by the Tor Project and packaged for Swift. The library resides in the local package directory at `localPackages/Arti/` and is imported throughout the app as a Swift package dependency.

Arti replaces legacy Tor bindings with a modern, memory-safe implementation that runs entirely within the app's sandbox. This eliminates external dependencies and ensures consistent behavior across iOS versions.

## Bootstrapping the Tor Daemon

The **Tor daemon initialization** follows a controlled lifecycle managed through the `Arti` class. When BitChat launches, the app creates an `Arti` client instance and invokes `start()` to spawn the embedded Tor process.

```swift
import Arti

class TorManager: NSObject, ArtiDelegate {
    private var arti: Arti?

    func startTor() {
        arti = Arti()
        arti?.delegate = self
        arti?.start()                // launches the Tor daemon
    }
}

```

The daemon builds circuits to the Tor network asynchronously. The `TorManager` class—located at [`BitChat/Network/TorManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BitChat/Network/TorManager.swift)—wraps this functionality and provides the primary interface used by other app components.

## Monitoring Circuit Status

BitChat tracks **Tor circuit readiness** through the `ArtiDelegate` protocol defined in [`localPackages/Arti/Sources/Arti/ArtiDelegate.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/Arti/Sources/Arti/ArtiDelegate.swift). The delegate receives callbacks for state transitions including circuit establishment, failure, and shutdown.

```swift
func arti(_ arti: Arti, didUpdateState state: Arti.State) {
    switch state {
    case .running:
        print("✅ Tor circuit is ready")
    case .failed(let error):
        print("❌ Tor failed: \(error)")
    default: break
    }
}

```

The UI layer at [`BitChat/UI/TorStatusView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BitChat/UI/TorStatusView.swift) consumes these events to display connection status—"Connecting to Tor…", "Tor ready", or error states—to users in real time.

## Routing Traffic Through the SOCKS5 Proxy

Once the Tor daemon establishes a circuit, it exposes a **local SOCKS5 proxy** on `127.0.0.1:9050`. BitChat intercepts all outbound HTTP/HTTPS traffic by configuring a custom `URLSessionConfiguration` with proxy settings.

```swift
func torEnabledSession() -> URLSession {
    let config = URLSessionConfiguration.default
    config.connectionProxyDictionary = [
        kCFNetworkProxiesSOCKSProxy: "127.0.0.1",
        kCFNetworkProxiesSOCKSPort: 9050,
        kCFNetworkProxiesSOCKSEnable: true
    ]
    return URLSession(configuration: config)
}

```

This configuration is centralized in `BitChat/Network/URLSession+Tor.swift` and applied to every `URLSession` the app instantiates. Messaging, file uploads, and push notification registration all flow through this **Tor-enabled networking layer**.

## Complete Request Flow

The following example demonstrates end-to-end **Tor-protected networking**:

```swift
let torMgr = TorManager()
torMgr.startTor()

let session = torEnabledSession()
let url = URL(string: "https://api.bitchat.example/message")!
session.dataTask(with: url) { data, resp, err in
    // …handle response (all traffic went through Tor)
}.resume()

```

## Graceful Shutdown and Resource Management

When BitChat enters the background or terminates, `Arti.stop()` shuts down the Tor daemon cleanly. This prevents traffic leaks outside the Tor tunnel and releases system resources. The shutdown sequence is integrated with iOS app lifecycle hooks to ensure **privacy protection** persists across state transitions.

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`localPackages/Arti/Sources/Arti/Arti.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/Arti/Sources/Arti/Arti.swift) | Core daemon control: `start()`, `stop()`, and circuit management |
| [`localPackages/Arti/Sources/Arti/ArtiDelegate.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/Arti/Sources/Arti/ArtiDelegate.swift) | Protocol for Tor state callbacks |
| [`BitChat/Network/TorManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BitChat/Network/TorManager.swift) | App-level wrapper coordinating Tor lifecycle |
| `BitChat/Network/URLSession+Tor.swift` | SOCKS5 proxy configuration for all network sessions |
| [`BitChat/UI/TorStatusView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BitChat/UI/TorStatusView.swift) | User-facing connection state display |

## Summary

- **Tor integration in BitChat** uses the Arti library to embed a full Tor client directly into the iOS app
- The daemon exposes a local SOCKS5 proxy at `127.0.0.1:9050` that tunnels all HTTP/HTTPS traffic
- `TorManager` and `ArtiDelegate` coordinate daemon lifecycle and surface connection status to users
- Custom `URLSessionConfiguration` forces every network request through the Tor circuit
- Clean shutdown via `Arti.stop()` prevents leaks and preserves resources

## Frequently Asked Questions

### Can BitChat work without Tor enabled?

BitChat's architecture routes all traffic through the embedded Tor daemon by default. The app does not expose a configuration to bypass the proxy, ensuring consistent **privacy protection** across all usage scenarios.

### Does BitChat require a separate Tor app or VPN profile?

No. Because Tor runs as an embedded daemon via Arti, no external apps, VPN configurations, or system-level changes are required. The entire stack operates within BitChat's app sandbox.

### How does BitChat handle Tor connection failures?

When `Arti` reports a failed state through the delegate protocol, [`TorStatusView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/TorStatusView.swift) displays the error to the user. The app may retry circuit establishment automatically or prompt the user to check network connectivity, depending on the failure type.

### What iOS versions support BitChat's Tor integration?

Arti's Rust-based implementation targets modern iOS versions with stable Swift Package Manager support. The embedded approach avoids legacy APIs, ensuring **Tor functionality** remains available as iOS evolves.