# Ruby Net::HTTP Proxy: Configure Auth, TLS, and Bounded Reads

[All guides](https://proxylane.dev/blog) 

DEVELOPER GUIDES · 6 MIN READ

Route Ruby Net::HTTP through an HTTP proxy, keep credentials separate, close sessions cleanly, and validate the target response.

**Founder, ProxyLane** Published September 18, 2026

On this page [Keep proxy credentials outside the URL](https://proxylane.dev/blog/ruby-net-http-proxy#keep-proxy-credentials-outside-the-url)  [Check the output your job needs](https://proxylane.dev/blog/ruby-net-http-proxy#check-the-output-your-job-needs)

**Residential proxies from $2.50/GB**

Non-expiring traffic, location targeting and rotating or sticky sessions for your existing tools.

 [Sign up](https://proxylane.dev/register?interest=proxies)

Ruby's standard `Net::HTTP` can send an HTTPS request through an HTTP proxy, but the proxy belongs in the connection object, while TLS belongs on the connection to the target. Keeping those two hops visible makes a 407, a target 403, and a connection timeout easier to act on.

 

The example below uses `Net::HTTP.new` with an HTTP proxy endpoint, makes an authorized `GET` to `https://example.com/`, bounds connection and read work, caps the body at 1 MiB, and closes the session with a block. It assumes Ruby 2.6 or later and uses only the standard library. Replace the target and marker with the resource your application is allowed to access.

 

## Keep proxy credentials outside the URL

 

`Net::HTTP.new` accepts the target address and port, followed by the proxy address, proxy port, username, and password. The example keeps `PROXY_URL` free of userinfo and passes the credentials as separate environment bindings:

 

```text
PROXY_URL=http://proxy.example:3128
PROXY_USER=account-name             # optional
PROXY_PASSWORD=bound-secret         # optional
```

 

This baseline intentionally supports an HTTP proxy endpoint. `use_ssl = true` enables TLS for the HTTPS target after the proxy connection is established; it does not turn the proxy itself into an HTTPS proxy. If your provider gives a different proxy protocol, select a Ruby client whose current API documents that protocol.

 

Save this as `proxy_get.rb`:

 

```ruby
require 'net/http'
require 'openssl'
require 'uri'

MAX_BODY_BYTES = 1 << 20

def required_env(name)
  value = ENV[name].to_s.strip
  raise "missing required environment binding: #{name}" if value.empty?

  value
end

def read_response(http, target)
  request = Net::HTTP::Get.new(target)
  status = nil
  body = +''

  http.request(request) do |response|
    status = response.code.to_i
    if status == 407
      raise 'proxy authentication or CONNECT negotiation returned HTTP 407'
    end

    response.read_body do |chunk|
      if body.bytesize + chunk.bytesize > MAX_BODY_BYTES
        raise 'response body exceeded local cap'
      end
      body << chunk
    end
  end

  [status, body]
end

target = URI('https://example.com/')
begin
  proxy = URI(required_env('PROXY_URL'))
rescue URI::InvalidURIError
  warn 'PROXY_URL is not a valid URI'
  exit 1
end
unless proxy.scheme == 'http' && !proxy.host.nil? && proxy.user.nil? && proxy.password.nil?
  raise 'PROXY_URL must be an HTTP proxy URL without credentials'
end

proxy_user = ENV['PROXY_USER']
proxy_password = ENV['PROXY_PASSWORD']
if proxy_user.nil? != proxy_password.nil?
  raise 'PROXY_USER and PROXY_PASSWORD must be supplied together'
end

http = Net::HTTP.new(
  target.host,
  target.port,
  proxy.host,
  proxy.port || 80,
  proxy_user,
  proxy_password
)
http.use_ssl = true
http.open_timeout = 5
http.read_timeout = 10
http.write_timeout = 10
http.max_retries = 0

begin
  http.start do |session|
    status, body = read_response(session, target)
    raise 'target returned a non-accepted HTTP status' unless status == 200
    raise 'target marker was absent' unless body.include?('Example Domain')

    puts "status=#{status} body_bytes=#{body.bytesize}"
  end
rescue Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout, SocketError, EOFError,
       Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
       OpenSSL::SSL::SSLError, Net::HTTPBadResponse, Net::ProtocolError
  warn 'request failed in transport or proxy negotiation'
  exit 1
end
```

 

Run it with the standard Ruby interpreter:

 

```sh
ruby proxy_get.rb
```

 

The `Net::HTTP.start` block closes the connection when it exits. `open_timeout` covers opening the connection to the proxy, while `read_timeout` and `write_timeout` apply to socket operations. The response block rejects a 407 before reading its body, then bounds accepted body data at 1 MiB. Malformed URI, TLS, and CONNECT failures exit with a generic message; the proxy URI and exception details never reach output.

 

This core example uses one attempt. If a worker adds retries for an idempotent `GET`, classify the failure first, honor a valid `Retry-After` value, and keep a job-level deadline. DNS, TLS, connection, configuration, and proxy-authentication failures should stop immediately because repeating an invalid password or an unreachable endpoint does not repair the route.

 

## Check the output your job needs

 

Use an application-level contract rather than counting a successful `request` call:

 

```text
input:  permitted HTTPS target + HTTP proxy host/port + expected marker
output: status=200, marker present, body <= 1 MiB, session closed
```

 

The marker is a placeholder for your own required field or schema. The target can return a valid HTTP status with an error page, login form, or challenge that your parser must reject.

 

| Observation | Boundary | Next decision |
| --- | --- | --- |
| Proxy URL has credentials or an unsupported scheme | Local configuration | Remove userinfo and use a documented HTTP proxy endpoint |
| Open/read/TLS exception before a response | Client, proxy, or CONNECT | Check proxy host, port, certificate, and reachability; do not retry blindly |
| HTTP 407 | Proxy authentication | Repair proxy credentials or entitlement; keep them away from target headers |
| HTTP 401 or 403 after CONNECT | Target policy | Check target login, permission, or target-side rules |
| HTTP 502, 503, or 504 | Temporary gateway or target response | Defer or retry only under an explicit policy that honors `Retry-After` |
| HTTP 200 with no marker | Application validation | Reject the result and inspect the content or parser |
| Body exceeds 1 MiB | Local resource policy | Reject or define another bounded streaming rule |

 

For the same phase-by-phase view in a terminal, read the  [curl proxy guide](https://proxylane.dev/blog/curl-proxy) .  [HTTP 407 troubleshooting](https://proxylane.dev/blog/proxy-error-407)  explains why a CONNECT challenge can appear as an exception, and  [proxy client settings](https://proxylane.dev/blog/proxy-client-settings)  covers cases where an application-specific route differs from the operating system.

 

ProxyLane's public residential offer starts from **$2.50/GB** with HTTP and SOCKS5 access, country, city, ISP, rotating and sticky options, and traffic that does not expire. Create a free account, then choose a traffic package separately; no payment is required at signup. Those are route and commercial inputs, not a Ruby benchmark or a target acceptance promise. When your target and acceptance rule are authorized,  [Sign up](https://proxylane.dev/register?interest=proxies) .

 

## Sources and further reading

- [https://ruby-doc.org/3.4.1/stdlibs/net/http/Net/HTTP.html](https://ruby-doc.org/3.4.1/stdlibs/net/http/Net/HTTP.html)

- [https://ruby-doc.org/3.4.1/stdlibs/net/http/Net/HTTPResponse.html](https://ruby-doc.org/3.4.1/stdlibs/net/http/Net/HTTPResponse.html)

- [https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.8](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.8)

[Sign up](https://proxylane.dev/register?interest=proxies)

## Keep reading

[Use cases · 3 min read

### Amazon Scraper API vs Proxy: Choose a Product Data Source

Distinguish authorized Amazon APIs, licensed product data and proxy-based page checks by record quality and access rights.

 Read guide](https://proxylane.dev/blog/amazon-scraper-api-vs-proxy)   [Integrations · 5 min read

### Apify Custom Proxy Setup: Use Your Own Residential Route

Connect a buyer-owned proxy to an Apify Actor, keep the session boundary clear, and validate records instead of counting requests.

 Read guide](https://proxylane.dev/blog/apify-custom-proxy)   [Proxy fundamentals · 6 min read

### Australia Residential Proxies: Verify the AU Exit and State-Level Result

Separate Australian egress from en-AU content, AUD pricing, GST display, postcode validation and the state delivery context.

 Read guide](https://proxylane.dev/blog/australia-residential-proxies)

Canonical source: https://proxylane.dev/blog/ruby-net-http-proxy

Documentation index: https://proxylane.dev/llms.txt
