flutter_tor
Native Flutter plugin for embedded Tor client using Tor.xcframework (iCepa) with obfs4/snowflake bridge support via IPtProxy.
Features
- Embedded Tor client — no external processes or VPN profiles required.
- SOCKS5 proxy with automatic port assignment.
- Bridge support: built-in obfs4 and snowflake presets, or custom bridge lines.
- Reactive streams for connection status and native logs.
- Hot-restart safe — native singleton preserves Tor state across Dart restarts.
Platform support
| iOS | macOS | Android | Web | Windows | Linux |
|---|---|---|---|---|---|
| ✅ | 🔜 | — | — | — | — |
Getting started
Requirements
- iOS 15.0+
- Flutter 3.3+
Installation
dependencies:
flutter_tor: ^0.1.0
Usage
Basic connection (no bridges)
import 'package:flutter_tor/flutter_tor.dart';
// Start Tor
await TorIos.initialize();
// Listen for status changes
TorIos.statusStream.listen((event) {
print('${event.status} ${event.progress}%');
});
// Get SOCKS5 proxy port once connected
final port = await TorIos.getProxyPort();
// Stop Tor
await TorIos.stop();
Using bridges
// Use built-in obfs4 bridges
await TorIos.initialize(TorBridgePresets.obfs4Default);
// Use snowflake
await TorIos.initialize(TorBridgePresets.snowflake);
// Use custom bridge lines
await TorIos.initialize(TorBridgeConfig(
useBridges: true,
bridgeLines: ['obfs4 198.51.100.1:443 ...'],
));
Making requests through Tor
Use the SOCKS5 proxy port with any HTTP client that supports SOCKS proxies (e.g., socks5_proxy):
import 'dart:io';
import 'package:socks5_proxy/socks_client.dart';
final port = await TorIos.getProxyPort();
final client = HttpClient();
SocksTCPClient.assignToHttpClient(client, [
ProxySettings(InternetAddress.loopbackIPv4, port),
]);
final request = await client.getUrl(Uri.parse('https://check.torproject.org/api/ip'));
final response = await request.close();
Controlling native logs
Native logs (NSLog and Tor stdout/stderr) can be disabled via a single flag. Set it before initialize() to also suppress Tor's early startup messages:
// Disable all native logs
TorIos.logsEnabled = false;
await TorIos.initialize();
// Re-enable at any time
TorIos.logsEnabled = true;
Recovering state after hot restart
Tor runs in a native singleton that outlives Dart restarts. Sync on startup:
final status = await TorIos.getStatus();
if (status.status == TorStatus.connected) {
final port = await TorIos.getProxyPort();
// ready to use
}
API overview
| Class | Description |
|---|---|
TorIos |
Main entry point — initialize(), stop(), getProxyPort(), getStatus(), statusStream, logStream, logsEnabled |
TorBridgeConfig |
Bridge configuration with useBridges, bridgeLines, useObfs4, useSnowflake |
TorBridgePresets |
Ready-to-use presets: obfs4Default, snowflake, noBridges |
TorStatus |
Enum: disconnected, connecting, connected, error |
TorStatusEvent |
Status snapshot with status, progress, errorMessage, bridges |
TorLogEvent |
Native log entry with level, tag, message, timestamp |
License
MIT License. See LICENSE for details.
Libraries
- flutter_tor
- Embedded Tor client for Flutter on iOS.