Getting a proxy to correctly register with Watir + Chrome can be difficult, as examples in the wild don’t always match the current reality, and documentation is a bit willy-nilly. The documentation for Watir says that you can pass a switches option to set the proxy in the Chrome startup arguments. This works when using Chrome directly, but does not when connecting to remote Selenium + Chrome with :remote (or, as :chrome but with a :url specified).

After a lot of trial and error, I got it sorted using the Selenium::WebDriver::Proxy object.

Many of the examples I’ve seen in the wild don’t seem to match what I’m seeing in my environment. Watir also abstracts away much of the required knowledge of Selenium configuration, and so it’s not always clear what you’re doing under the hood.

The Selenium::WebDriver::Capabilities object allows you to request certain specifications from your browser. You can pass a Capabilities object when creating a new Watir::Browser instance. Capabilities has a :proxy option that allows you to set the proxy to be used.

Usage

First, I’m trying to use Chrome remotely using the Docker Selenium Chrome container. Run this and toss it to the side…

docker run --rm -p 4444:4444 -p 5900:5900 selenium/standalone-chrome-debug

This fires up a remote selenium container to test against. Selenium is now listening for connections on 4444, and as a nice feature of the -debug variant, you can VNC over to localhost:5900 to see how it’s going.

require 'watir'

# Some tools require your proxy string to be prefixed with `http://`
# FYI, Selenium won't care, so don't worry about it.

PROXY = "127.0.0.1:8080"  # Replace with an actual proxy


##
# We'll create the Proxy specs next.
#
# Notice how I need to set both :http and :ssl separately below.
# Also notice that the key is `:ssl` instead of `:https`!
# If you do not set both, your proxy may not be as proxiful as you expect.

proxy = Selenium::WebDriver::Proxy.new http: PROXY, ssl: PROXY

# This is a factory for creating capabilities objects that you can pass into `desired_capabilities`.
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome

capabilities[:proxy] = proxy

browser = Watir::Browser.new :chrome, url: 'http://localhost:4444/wd/hub', desired_capabilities: capabilities

browser.goto 'https://api.ipify.org'

# hooray!

In the current versions of Watir, you’ll receive deprecation warnings when you pass :desired_capabilities. Watir 6.6 introduces the ability to pass the same options directly to the Watir initializer:

proxy = Selenium::WebDriver::Proxy.new http: PROXY, ssl: PROXY
browser = Watir::Browser.new :chrome, url: REMOTE_URL, proxy: proxy

In addition, the Capabilities object is able to create the Selenium::WebDriver::Proxy object on the fly, as long as you pass in the relevant initialization hash:

browser = Watir::Browser.new :chrome, url: REMOTE_URL, proxy: {http: PROXY, ssl: PROXY}

Gotchas

Capabilities expects a formal Selenium::WebDriver::Proxy object.

If you try using a string, you will receive either:

NoMethodError: undefined method `as_json' for "127.0.0.1:8800":String
# or
TypeError: expected Hash or Selenium::WebDriver::Proxy, got "127.0.0.1:8080":String

depending on how you try setting the value. I wanted to note those error messages specifically, as the first one in particular was the one that I most often saw, and was quite unhelpful.

When specifying capabilities[:proxy], you can either give it the full object, or a hash that would be used to create one.

Don’t forget to set both :http and :ssl

Outro

I wanted to spend the time writing this out because I felt that the current resources out there were hard to find. Hopefully you got here without too much stress, and things haven’t changed too much. If you find this is no longer relevant, shoot me a message below.