Search code examples
c#seleniumfirefoxgeckodrivertor

C# Selenium - Failed to Start Tor


I'm trying to launch Tor browser through Selenium in C# using the following code:

using OpenQA.Selenium.Firefox;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AutomatorApp
{
  public class BrowserAutomator
  {
     public void Automate()
     {

        String torPath = "D:\\Tor Browser\\Browser\\firefox.exe";
        String profilePath = "D:\\Tor Browser\\Browser\\TorBrowser\\Data\\Browser\\profile.default\\";

        FirefoxProfile profile = new FirefoxProfile(profilePath);
        profile.SetPreference("network.proxy.type", 1);
        profile.SetPreference("network.proxy.socks", "127.0.0.1");
        profile.SetPreference("network.proxy.socks_port", 9153);
        profile.SetPreference("network.proxy.socks_remote_dns", false);

        FirefoxDriverService firefoxDriverService = FirefoxDriverService.CreateDefaultService("D:\\geckodriver-v0.26.0-win64", "geckodriver.exe");
        firefoxDriverService.FirefoxBinaryPath = torPath;

        var firefoxOptions = new FirefoxOptions
        {
            Profile = profile,
            LogLevel = FirefoxDriverLogLevel.Trace
        };

        FirefoxDriver driver = new FirefoxDriver(firefoxDriverService, firefoxOptions);
      }
   }
}

However, this shows the error 'Tor Failed to Start' and the exception simply contains 'Permission denied'. I tried launching the app in administrator mode and ensuring that the folder is accessible by all users but this did not solve the issue.

Interestingly, when I try to launch a Firefox browser using the same setup it works well.

Any help is very much appreciated.

Update - Solved: After updating to the latest Tor version (9.5.1) The final working code:

            FirefoxProfile profile = new FirefoxProfile(profilePath);
            profile.SetPreference("network.proxy.type", 1);
            profile.SetPreference("network.proxy.socks", "127.0.0.1");
            profile.SetPreference("network.proxy.socks_port", 9153);
            profile.SetPreference("network.proxy.socks_remote_dns", false);

            FirefoxDriverService firefoxDriverService = FirefoxDriverService.CreateDefaultService(geckoDriverDirectory);
            firefoxDriverService.FirefoxBinaryPath = torPath;
            firefoxDriverService.BrowserCommunicationPort = 2828;
            var firefoxOptions = new FirefoxOptions
            {
                Profile = null,
                LogLevel = FirefoxDriverLogLevel.Trace
            };
            firefoxOptions.AddArguments("-profile", profilePath);
            FirefoxDriver driver = new FirefoxDriver(firefoxDriverService, firefoxOptions);
            driver.Navigate().GoToUrl("https://www.google.com");

Important notes:

The following TOR configs need to be changed in about:config :

  • marionette.enabled: true

  • marionette.port: set to an unused port, and set this value to firefoxDriverService.BrowserCommunicationPort in your code. This was set to 2828 in my example.


Solution

  • As far as I remember from my attempts a few years ago, TOR with WebDriver didn't work when you set that "Profile" option. Normal Firefox works, but TOR simply doesn't.

    If you get a timeout error after this, make sure marionette is enabled on about:config. If it's already enabled, follow what is going on with TOR on start up. Like if the actual firefox browser doesn't load up, stuck at connection launhcer etc, or there is a message box at the browser startup or something... And also make sure no other firefox.exe, geckodriver.exe or tor.exe is running on the background. If multiple executubles are not configured to listen different port numbers, it might cause problems.

        Environment.SetEnvironmentVariable("webdriver.gecko.driver", "C:\\TorBrowser\\Browser\\geckodriver.exe");
        var gekcoService = FirefoxDriverService.CreateDefaultService("C:\\TorBrowser\\Browser", "geckodriver.exe");
        var gekcoService.FirefoxBinaryPath = "C:\\TorBrowser\\Browser\\firefox.exe";
    
        // marionette port that browser listens to. I had it set to a custom port on about:config
        var gekcoService.BrowserCommunicationPort = 50111; 
    
        // also had given a custom port for geckodriver listen port
        var gekcoService.Port = 9881; 
        var gekcoService.Host = 127.0.0.1;
        var gekcoService.HostName = 127.0.0.1;
        var gekcoService.Start();
        
        var ffOptions = new FirefoxOptions
        {
            AcceptInsecureCertificates = true,
            BrowserExecutableLocation = "C:\\TorBrowser\\Browser\\firefox.exe",
            Profile = null, 
            UnhandledPromptBehavior = UnhandledPromptBehavior.Dismiss
        };
        
        ffOptions.AddArguments("-profile", "C:\\TorBrowser\\Browser\\TorBrowser\\Data\\Browser\\profile.default");
        ffOptions.LogLevel = FirefoxDriverLogLevel.Info;
        ffOptions.PageLoadStrategy = PageLoadStrategy.Eager;
        var ffDriver = new FirefoxDriver(gekcoService, ffOptions);
        ffDriver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(10);
        ffDriver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(10);
        ffDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);