Ruby · setup guide

Ruby proxy setup

Ruby's standard library takes a proxy as four extra arguments to Net::HTTP.new: host, port, user and password. Faraday takes a proxy: option and HTTParty an http_proxy line in the class, and both run on Net::HTTP by default, so they share its habits: 60-second timeouts, and a proxy read from http_proxy when you pass none.
You will need

Residentialresi.proxymonkey.io:8000

ISP or datacenterIP:PORT

CredentialsUSER:PASS

Copy your own from the dashboard, which also lists the host and port for every order. Where it differs from this page, the dashboard is right.

Install

Net::HTTP ships with Ruby. The gems are only for the Faraday and HTTParty examples.

terminal
gem install faraday httparty

Rotating residential

The proxy arguments follow the target's host and port. Calling get on a Net::HTTP that has not been started opens a connection for that one request and closes it afterwards, so each pass of the loop goes out through a new tunnel and a new residential address.

rotate.rb
require "json"
require "net/http"

PROXY_HOST = "resi.proxymonkey.io"
PROXY_PORT = 8000
uri = URI("https://httpbin.org/ip")

3.times do
  http = Net::HTTP.new(uri.host, uri.port, PROXY_HOST, PROXY_PORT, "USER", "PASS")
  http.use_ssl = true
  http.open_timeout = 10
  http.read_timeout = 30
  puts JSON.parse(http.get(uri.path).body)["origin"]
end

A static datacenter or ISP IP

Faraday takes the whole proxy URL in proxy:, credentials included, and the timeouts under request:. This one runs on your static datacenter IP. For an ISP order, use the host and port your dashboard lists for it.

static.rb
require "faraday"

conn = Faraday.new(
  url: "https://httpbin.org",
  proxy: "http://USER:PASS@IP:PORT",
  request: { open_timeout: 10, timeout: 30 },
)

%w[/ip /headers].each do |path|
  res = conn.get(path)
  puts res.status, res.body[0, 80]
end

Keeping one identity

Inside one Net::HTTP.start block, requests share a single connection, and so a single tunnel and exit address. That is the simplest way to hold an address for a short multi-step flow on the rotating gateway. Net::HTTP keeps no cookies between requests; you carry Set-Cookie values yourself. For an address that holds across connections and runs, use a static IP or a residential sticky session; the session setting for your account is in the dashboard.

Specific to Ruby

Things worth knowing

HTTParty: one line in the class

http_proxy takes the host, port, user and password separately, and HTTParty builds a new Net::HTTP for each call, so on the rotating gateway every call leaves from a new address. The host is a bare name, not a URL.

catalogue.rb
require "httparty"

class Catalogue
  include HTTParty
  base_uri "https://httpbin.org"
  http_proxy "resi.proxymonkey.io", 8000, "USER", "PASS"
  default_timeout 30
end

puts Catalogue.get("/ip").body

Faraday without the password in the URL

A password with @, : or / breaks a proxy URL. Faraday also takes the proxy as a hash, with the credentials as plain strings beside it.

proxy_hash.rb
conn = Faraday.new(
  url: "https://httpbin.org",
  proxy: { uri: "http://resi.proxymonkey.io:8000", user: "USER", password: "PASS" },
)

Count the bytes Net::HTTP hides

We meter request bytes plus response bytes, headers included. Net::HTTP asks for gzip by default, then decompresses the body and deletes the Content-Encoding header, so body.bytesize is the decoded size. Set Accept-Encoding yourself and it leaves the body as it arrived. The sum skips the request and status lines, and TLS overhead makes ours slightly higher.

wire_bytes.rb
req = Net::HTTP::Get.new(uri, "Accept-Encoding" => "gzip")
res = http.request(req)

head = ->(h) { h.each_capitalized.sum { |k, v| k.size + v.size + 4 } }
puts head.(req) + head.(res) + res.body.bytesize
When it breaks

Common errors and fixes

  • Net::HTTPClientException: 407 "Proxy Authentication Required"

    Why
    The gateway refused the CONNECT for an HTTPS URL, and Net::HTTP raises on it while connecting. On a plain http:// target you get a Net::HTTPProxyAuthenticationRequired response instead.
    Fix
    Pass the user and password as separate arguments, which need no escaping, and copy them fresh from the dashboard.
  • Net::OpenTimeout or Net::ReadTimeout after a minute

    Why
    Net::HTTP waits 60 seconds to connect and 60 to read by default, a long time to hold on a dead residential exit.
    Fix
    Set open_timeout = 10 and read_timeout = 30, rescue both and retry. Each retry is a new connection and, on the rotating gateway, a new address.
  • OpenSSL::SSL::SSLError ending in certificate verify failed

    Why
    The target's certificate or your CA store. TLS runs through the tunnel to the target; the proxy is not part of it.
    Fix
    Update your CA certificates or point ca_file at the right bundle. verify_mode = OpenSSL::SSL::VERIFY_NONE is for a one-off test only.
  • Traffic goes through a proxy you never configured, or not through yours

    Why
    When you pass no proxy host, Net::HTTP reads one from http_proxy in the environment, and HTTParty without http_proxy does the same.
    Fix
    Pass the proxy explicitly, or nil as the proxy host to go direct, and check the environment of the process that runs the job.

A failed connection that moved no data is not billed. Retries you send are billed like any other request, and each shows as its own line in your usage log.

The community layer

Ruby still misbehaving?

Paste the error and the few lines that set up the proxy into Discord, with the password taken out. Someone there has seen it before.

Join the Discord

4,200+monkeys in the Discord

  • Help from humans

    Post your error, get an answer. Usually in minutes, usually from someone who has hit the same wall.

  • A status bot that tells on us

    Pool health, incidents and maintenance posted automatically. Including the bad days.

  • Deals and free traffic

    Bonus GB drops, early access to new pools, and the occasional giveaway for a good bug report.

Join the Discord4,200+ monkeys, free to lurk