An open-source, privacy-enhancing web browser for iOS, utilizing the Tor anonymity network
Clone or download
Pull request Compare This branch is 60 commits behind OnionBrowser:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Onion Browser

Build Status
Official Site | Support | Changelog
© 2012-2015 Mike Tigas (@mtigas)
MIT License

A minimal, open-source web browser for iOS that tunnels web traffic through the Tor network. See the official site for more details and App Store links.

Screenshots: iPhone 4/4S, iPhone 5, iPad 3

Integration notes

Onion Browser responds to two URL schemes: onionbrowser:// and onionbrowsers://, representing HTTP and HTTPS URLs, respectively. These work like the URI schemes in iOS Google Chrome and other popular third-party web browsers.

  • A URL of onionbrowser:// will launch Onion Browser and navigate the app to
  • A URL of onionbrowsers:// will launch Onion Browser and navigate the app to

Allowing your own app to launch Onion Browser instead of Safari works similarly to iOS Google Chrome:

  1. Check if Onion Browser is installed by seeing if iOS can open a onionbrowser:// URL.
  2. If so, replace the http:// prefix with onionbrowser:// and replace the https:// prefix with onionbrowsers://.
  3. Then tell iOS to open the newly defined URL (newURL) by executing [[UIApplication sharedApplication] openURL:newURL];

See the Google Chrome iOS instructions for more details -- just note that you should replace their googlechrome:// URL schemes with the proper onionbrowser:// ones.

Compilation notes

The app, when compiled, contains static library versions of Tor and it's dependencies, libevent and openssl.

The build scripts for Tor and other dependencies are based on from x2on/OpenSSL-for-iPhone. The scripts are configured to compile universal binaries for armv7 and i386 (for the iOS Simulator).

The tor script patches one file in Tor (src/common/compat.c) to remove references to ptrace() and _NSGetEnviron(). This first is only used for the DisableDebuggerAttachment feature (default: True) implemented in Tor (See changelog and manual.) ptrace() and _NSGetEnviron() calls are not allowed in App Store apps; apps submitted with ptrace() symbols are rejected on upload by Apple's auto-validation of the uploaded binary. (The _NSGetEnviron() code does not even compile when using iPhoneSDK due to that function being undefined.) See the patch files in build-patches/ if you are interested in the changes.

Tor introduced compiler and linker "hardening" (Tor ticket 5210), which is incompatible with the iOS Device build chain. The app (when building for iOS devices) is configured with --disable-gcc-hardening --disable-linker-hardening to get around this issue. (Due to the isolation of executable code on iOS devices, this should not cause a significant change in security.)

Because iOS applications cannot launch subprocesses or otherwise execute other binaries, the tor client is run in-process in a NSThread subclass which executes the tor_main() function (as an external tor executable would) and attempts to safely wrap Tor within the app. (libor.a and libtor.a, intermediate binaries created when compiling Tor, are used to provide Tor.) Side-effects of this method have not yet been fully evaluated. Management of most tor functionality (status checks, reloading tor on connection changes) is handled by accessing the Tor control port in an internal, telnet-like session from the AppDelegate.

The app uses a NSURLProtocol subclass (ProxyURLProtocol), registered to handle HTTP/HTTPS requests. That protocol uses the CKHTTPConnection class which nearly matches the NSURLConnection class, providing wrappers and access to the underlying CFHTTP Core Framework connection bits. This connection class is where SOCKS5 connectivity is enabled. (Because we are using SOCKS5, DNS requests are sent over the Tor network, as well.)

(I had WireShark packet logs to support the claim that this app protects all HTTP/HTTPS/DNS traffic in the browser, but seem to have misplaced them. You'll have to take my word for it or run your own tests.)

The app uses Automatic Reference Counting (ARC) and was developed against iOS 5.X or greater. (It may work when building against iOS 4.X, since most of the ARC behavior exists in that older SDK, with the notable exception of weakrefs.)


  1. Check Xcode version
  2. Build dependencies via command-line
  3. Build application in XCode

Check Xcode version

Double-check that the "currently selected" Xcode Tools correspond to the version of Xcode you have installed:

xcode-select -print-path

For the newer Xcode 4.3+ installed via the App Store, the directory should be /Applications/, and not the straight /Developer (used by Xcode 4.2 and earlier). If you have both copies of Xcode installed (or if you have updated to Xcode 4.3 but /Developer still shows), do this:

sudo xcode-select -switch /Applications/

Optional: PGP key verification for dependencies

(Currently in testing.) The build scripts for OpenSSL, libevent, and tor, verify that the package downloaded is PGP signed by one of the users responsible for packaging the library. You'll need to have GnuPG installed and import their public keys to allow this to work.

If you don't care about PGP key verification, you'll need to run each of the scripts with the --noverify option or change VERIFYGPG to false in each of the build-*.sh scripts before continuing.)

Building dependencies

cd to the root directory of this repository and then run these commands in the following order to build the dependencies. (This can take anywhere between five and thirty minutes depending on your system speed.)


This should create a dependencies directory in the root of the repository, containing the statically-compiled library files.

If you are inside a country or network that blocks connections to, you may have to use a mirror (alt) to successfully build the Tor dependency. Please see the instructions in if you require this.

Build OnionBrowser.xcodeproj in Xcode

Open OnionBrowser/OnionBrowser.xcodeproj. You should be able to compile and run the application at this point.

The app and all dependencies are compiled to run against arm64 and armv7 platforms (the default as of iOS 8).

All dependencies are further compiled for i386 and x86_64 targets, so that both the 32-bit and 64-bit iOS Simulators are supported.

Information for forks

  1. If you're distributing an app that builds off of the Onion Browser code, you need to use your own app name and logo.

  2. If you're distributing an app that builds off of the Onion Browser code, you need to cite Onion Browser within your app's credits as part of the terms of the normal MIT License.

    See the LICENSE file for information -- generally you need to include everything from the "ONION BROWSER LICENSE" section down through the rest of the file, but see the "TRADEMARK / LICENSE / FORK INFORMATION" section there.

  3. You'll need to make sure the "Bundle identifier" (under "Info" in the app's Target Properties) is set to your own identifier and not "com.miketigas.OnionBrowser".

  4. You'll need to make sure the URL handlers for your app (see Integration notes above) don't conflict with the ones for Onion Browser. Make sure you edit your <app>-Info.plist file and edit values under "URL types".

    Change "URL identifier" to your own' app's identifier from #3, change the URL Schemes to the URL schemes your app should open if another app tries to open a URL with that prefix. ("test" and "tests" will make your app open if another app tries to open URLs starting with "test://" and "tests://".)

    You'll also need to edit code in AppDelegate.m. Look for instances of "onionbrowser:" and "onionbrowsers:", as these are the portions that check for your app's URL identifiers.