v1.10.82-f67ee7d
Skip to main content
← Back to Code Snippets

Java HttpClient Proxy

Complete HttpClient proxy integration example for Java with Hex Proxies. Includes authentication, timeouts, and error handling.

JavaHttpClient
Install:Requires Java 11+. No additional dependencies.
Java / HttpClient
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class ProxyExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newBuilder()
            .proxy(ProxySelector.of(
                new InetSocketAddress("gate.hexproxies.com", 8080)))
            .authenticator(new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("user", "pass".toCharArray());
                }
            })
            .connectTimeout(Duration.ofSeconds(10))
            .build();

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://httpbin.org/ip"))
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();

        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString());
        System.out.println("Origin IP: " + response.body());
    }
}

Why Java for Proxy Work

Java's position in enterprise software development makes it a natural choice for proxy integrations that must meet corporate standards for reliability, security, and maintainability. The Java 11+ HttpClient is a modern, non-blocking HTTP implementation built into the standard library, eliminating the need for third-party dependencies in proxy configurations. This is significant in enterprise environments where every external dependency requires security review and license compliance. Java's strong typing, compile-time checks, and extensive monitoring tooling (JMX, JFR, JVisualVM) provide the observability that production proxy workloads demand.

Java's thread model, especially with virtual threads introduced in Java 21 (Project Loom), makes it competitive with Go and Node.js for high-concurrency proxy workloads. A single JVM can run millions of virtual threads, each making proxied HTTP requests through gate.hexproxies.com:8080, with scheduling handled by the runtime rather than the OS. This represents a fundamental shift for Java proxy programming, as traditional thread-per-request models were limited to hundreds of concurrent connections before hitting memory and scheduling limits.

Configuration Patterns

Java's HttpClient uses the builder pattern to compose proxy configuration, authentication, timeouts, and protocol preferences into an immutable client instance. The `ProxySelector.of()` method creates a selector that routes all traffic through a single proxy address. For more complex routing, implement a custom `ProxySelector` subclass whose `select()` method returns different proxy addresses based on the destination URI, enabling geographic routing or load balancing across multiple proxy endpoints.

The `Authenticator` mechanism handles proxy authentication by responding to authentication challenges from the proxy server. Java's HttpClient calls `getPasswordAuthentication()` when the proxy returns a 407 status, providing the request context so you can return different credentials for different proxy servers. For production deployments, read credentials from a secrets manager or environment variables rather than hardcoding them in the Authenticator implementation.

Common Pitfalls

Java's HttpClient has a subtle interaction with system proxy settings. If you do not explicitly set a ProxySelector, the client falls back to `ProxySelector.getDefault()`, which reads `http.proxyHost` and `https.proxyHost` system properties. These properties can be set by JVM arguments, application servers, or other libraries, potentially routing your traffic through an unintended proxy. Always set the ProxySelector explicitly in your client builder to maintain deterministic routing.

The Authenticator's threading behavior can cause issues in concurrent proxy workloads. Java's Authenticator is a global singleton set via `Authenticator.setDefault()`, but the HttpClient builder accepts a per-client Authenticator. If you set a default Authenticator and also pass one to the builder, the builder's Authenticator takes precedence for that client, but other HTTP components in the JVM still use the default. This can lead to credential cross-contamination in applications that use multiple proxy accounts.

Performance Optimization

Configure the HttpClient for optimal proxy throughput by enabling HTTP/2 with `.version(HttpClient.Version.HTTP_2)`. HTTP/2 multiplexing allows multiple requests to share a single TCP connection through the proxy, reducing handshake overhead. The HttpClient manages an internal connection pool that persists across requests, so reusing the same client instance for all proxy requests is essential for performance.

For batch proxy operations, use the `sendAsync()` method with CompletableFuture composition. Chain `.thenApply()` for response processing and `.exceptionally()` for error handling, then use `CompletableFuture.allOf()` to wait for all in-flight proxied requests. With virtual threads (Java 21+), you can also use structured concurrency via `StructuredTaskScope` to manage groups of proxy requests that should succeed or fail together, with automatic cleanup of remaining requests if one fails.

Tips

  • 1
    Java 11+ HttpClient has built-in proxy and authenticator support with no external deps.
  • 2
    Reuse the HttpClient instance across requests for connection pooling.
  • 3
    Set separate connect and request timeouts for better failure isolation.

Ready to Integrate?

Get proxy credentials and start coding in minutes.