Using a proxy with Watir + Chrome Remote
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.