Skip to content
Documentation Developers Guides

Automated Testing with Selenium and WonderProxy

Worldwide testing, local infrastructure

Selenium is a browser automation framework, primarily used for testing—if you're already doing end-to-end tests in your application, it's a good bet you're using Selenium. Using Selenium and PhantomJS, you can automate your WonderProxy-driven geoIP testing right on your local machine.

For the code samples and setup instructions below, we'll use a working demo, available on Github, that runs a few tests against the WonderNetwork GeoTest page.

Step 1: Set up your local Selenium environment

Initializing a local Selenium server is nice and easy, so we'll do that first.

  1. Go get the stand-alone server (packaged as a Java archive) from Selenium's download page:
    $ wget
  2. Spin it up with your local Java installation:
    $ java -jar selenium-server-standalone-3.7.1.jar
    It starts with some sensible defaults, but you can configure them to your heart's content! Run the server with a -h flag for details.

Step 2: Get PhantomJS

PhantomJS is a "headless" browser engine that acts just like a regular browser without the graphical user interface. It's ideal for testing website behavior and content when you're not overly concerned with styling and display.

  1. Follow the official download instructions. (On bigger Linux distributions, you can generally use the native package manager.)
  2. Make sure the phantomjs executable is in your $PATH:
    $ sudo ln -s /path/to/phantomjs /usr/local/bin/phantomjs

Wait a minute, why are you using all this old tooling?

Great question! You're right: the PhantomJS project has been suspended, and Selenium 3.7.1 released in November 2017. Why aren't we using the latest and greatest?

Sadly, modern tooling doesn't support authenticated proxies, or proxies like ours that require a username and password. Neither Headless Chrome nor Headless Firefox allow Selenium to configure proxy authentication. PhantomJS does, but it's only supported by older versions of Selenium. That's what we're using here.

If you are using IP Authentication, you don't have to worry about proxy authentication, so you can use whichever browser driver you like! If you can't use IP Authentication but you need modern browsers, our integration with SauceLabs might be right up your alley.

If you need modern tooling with standard proxy authentication, and you don't need Selenium, check out our Playwright guide.

Step 3: Configure Selenium to use WonderProxy

Writing Selenium tests is extensively covered in books, webinars, articles and videos, so we won't go in depth on the topic here. Instead, we'll focus on integrating WonderProxy using Selenium's DesiredCapabilities interface. DesiredCapabilities allows testers to customize browser configurations; in our case, we will customize PhantomJS to proxy its connections through a WonderProxy server.

At WonderProxy, proxy tokens replace passwords in your server credentials. Proxy tokens are quick to generate and work instantly across the network. Generate one (or five), and then use them anywhere your proxy configuration asks for a password.

Proxy tokens are part of our Delegated Authentication system.

The PHP and Python demo tests read your WonderProxy credentials from the local environment, so set that up first:

$ export WONDERPROXY_USER=username
$ export WONDERPROXY_TOKEN=proxytoken

In the code samples below, we pass a proxy server (like into the proxied() method as an argument. Then, proxied() plugs our proxy and proxy credentials into Selenium's PhantomJS driver, using DesiredCapabilities. Finally, proxied() returns the customized driver, which will direct all its requests through the proxy server.


    protected function proxied($proxy) {
        $capabilities = DesiredCapabilities::phantomjs();
        return RemoteWebDriver::create($this->selenium, $capabilities);


    def proxied(self, proxy):
        capabilities = DesiredCapabilities.PHANTOMJS.copy()
        capabilities['phantomjs.cli.args'] = [
            '--proxy=' + proxy,
            '--proxy-auth=' + evar.get('WONDERPROXY_USER') + ':' + evar.get('WONDERPROXY_TOKEN')

        return webdriver.Remote(

Step 4: Get testing!

Now that we've configured Selenium's WebDriver to shunt connections through WonderProxy, we can write some tests using the proxied driver.


The PHPUnit testing framework supports "parameterized" tests (tests that can be run multiple times with varied input) out of the box with its @dataProvider notation. In this sample, the userLocations() method will be the input source for our test. It include three sets of input, each containing the proxy to be tested and the expected output.

    public function userLocations() {
        return [
            ['', 'Albuquerque'],
            ['', 'Toronto'],
            ['', 'Vancouver'],

The test itself grabs a proxied driver, then loads up a web page and checks the user-city element.

     * @dataProvider userLocations
    public function testUserLocation($proxy, $expected) {
        $this->driver = $this->proxied($proxy);

        $search = $this->driver->findElement(WebDriverBy::id('user-city'));
        $this->assertContains($expected, $search->getText());

The element should read Toronto for the toronto proxy, Vancouver for the vancouver proxy, etc.


Python's unittest framework does not include parameterized test support, but the gist is the same as above: The test creates a proxied driver, then checks the user-city element against the proxy.

    def testUserLocationAlbuquerque(self):
        self.driver = self.proxied('')
        search = self.driver.find_element_by_id('user-city')
        self.assertIn('Albuquerque', search.text)

These code samples are part of a working demo, which is available on Github.

Take the uncertainty out of localization testing

Scalable testing options and a global network of proxy servers, right at your fingertips. No more guesswork.