Java Proxy Setup: HttpClient and OkHttp Authentication

Configure Java HttpClient and OkHttp with explicit proxy routing, safe authentication, HTTPS CONNECT, strict TLS and measured local diagnostics.

Written by the Mexela Editorial Team. Technical guides are reviewed by the Mexela Technical Team under the Mexela Editorial Policy.

PROXY OPTIONS

Choose a proxy endpoint for this integration

After verifying the configured client, compare private proxy options and pricing. Check the endpoint protocol, authentication and destination compatibility for the runtime that will make your requests.

For a Java HTTP proxy, configure the client that sends the request: use a ProxySelector and client-scoped Authenticator with JDK HttpClient, or an explicit Proxy and proxyAuthenticator with OkHttp. Keep credentials separate from URLs, verify destination certificates, and compare one direct request with the same approved destination through the proxy.

Reviewed and locally tested: October 13, 2026. We executed Windows Temurin 21.0.11 and OkHttp 4.12.0 with Okio JVM 3.6.0 and Kotlin 1.9.10. These are tested versions, not a statement that they are the newest. The examples select HTTP/1.1; other JDK builds, Android, HTTP/2 and SOCKS are outside this lab.

Choose the Java client and check its build

JDK java.net.http.HttpClient is available from Java 11. This downloadable diagnostic specifically requires Java 21 because it closes HttpClient through its newer lifecycle API. It is different from the older HttpURLConnection handler. A setting that works in one handler does not establish behavior in another. See the Java 21 HttpClient reference.

OkHttp is a separate library. This guide pins the 4.12.0 Java API rather than assuming a newer dependency has the same build requirements. The combined source needs its seven recorded Maven artifacts even when you select the JDK branch. The supplied build script downloads them locally and checks SHA-256 hashes. Run java -version and javac -version in the application environment before copying examples.

Run the tested diagnostic

Download the Java proxy source examples and read the README. The ZIP contains ProxyRequest.java, build.ps1 and the dependency manifest; it contains no credentials or binary libraries. In its extracted directory, use PowerShell:

./build.ps1
java -cp 'classes;lib/*' ProxyRequest jdk
java -cp 'classes;lib/*' ProxyRequest okhttp

Supply an approved CHECK_URL through the process environment. For proxy routing, supply a credential-free PROXY_ENDPOINT, such as http://proxy.example:8080, and separate PROXY_USER and PROXY_PASSWORD secret variables. Both credentials must be present together. This helper accepts HTTP proxy transport only. Unix Java classpaths use classes:lib/* instead of a semicolon.

For the direct control, remove those three proxy variables from the diagnostic process and request the same destination. The helper explicitly disables proxy selection in that branch. Run each command separately and inspect its JSON: a failed network check can still produce a normal process exit because the failure is reported as structured metadata.

JDK HttpClient: select and authenticate the proxy

The JDK branch sets ProxySelector.of(address) on its builder; its direct branch uses HttpClient.Builder.NO_PROXY. Supplying this selector avoids the default selector’s proxy and bypass rules. Our actual requests stayed direct with hostile JVM proxy defaults, and stayed proxied with http.nonProxyHosts=*. This is a client choice, not a change to the entire application. The builder reference documents explicit selection.

The authenticator checks RequestorType.PROXY, the configured host and port, and the Basic scheme before returning credentials. It does not answer destination-server challenges or call Authenticator.setDefault(). Credentials belong to the proxy authentication callback, not an ordinary destination Authorization header. Read username/password versus IP authentication when selecting the endpoint’s actual access method.

Why HTTP works but JDK HTTPS CONNECT returns 407

An HTTPS destination through an HTTP proxy first requires a CONNECT tunnel, then a TLS handshake with the destination. The destination’s https:// scheme does not mean your proxy endpoint uses HTTPS transport. Basic credentials sent to an HTTP proxy are not encrypted by the later destination TLS session.

The JDK’s jdk.http.auth.tunneling.disabledSchemes policy disables Basic CONNECT authentication by default. Our default JVM returned 407 even with valid fixture credentials. If your administration policy explicitly allows Basic on the selected proxy path, the owned diagnostic can be launched with:

java '-Djdk.http.auth.tunneling.disabledSchemes=' -cp 'classes;lib/*' ProxyRequest jdk

This startup option affects authentication policy across that JVM. Assess the transport before enabling it; do not edit the shared JDK installation or weaken destination TLS. The Java 21 networking properties explain the policy and authentication retry limits. Our approved local child JVM successfully established CONNECT with strict destination trust.

OkHttp: use proxyAuthenticator and stop repeated attempts

The OkHttp branch uses new Proxy(Proxy.Type.HTTP, address), with Proxy.NO_PROXY for direct requests. Its proxyAuthenticator checks the actual proxy route and returns a request with Proxy-Authorization. It declines further attempts when that header is already present. Destination authentication uses a different callback.

OkHttp also calls the proxy authenticator before CONNECT with a synthetic OkHttp-Preemptive challenge. The helper handles that separately from a real Basic challenge; a logging interceptor is not a replacement for the CONNECT callback. This behavior is described in the versioned OkHttp 4.12.0 authenticator source. OkHttp succeeded in our authenticated HTTPS fixture without the JDK tunneling switch.

Keep TLS strict and bound response reading

Leave CA_FILE unset to use normal runtime trust. For an approved private CA, supply its PEM bundle. The helper constructs a client-specific trust manager containing that bundle, replacing the default public roots for this client. Hostname verification stays enabled. Both clients rejected an untrusted certificate and a separately trusted certificate for the wrong hostname. Obtain CA material through a trusted administrative channel; see the Java 21 JSSE reference.

CONNECT_TIMEOUT_MS defaults to 2000 and REQUEST_TIMEOUT_MS to 5000. The JDK helper adds a bounded wait for its complete-body sendAsync() future and cancels on deadline. Treat a streaming body handler separately; receiving headers does not prove the body has completed. See the request timeout reference.

OkHttp sets connect, read and complete-call timeouts. The last one includes response reading, as documented in its 4.12.0 client source. Our 350 ms body-stall deadlines terminated both calls; reported request-plus-cleanup times were 440 ms for JDK and 407 ms for OkHttp. Client initialization added separate overhead. These are fixture observations, not proxy speed measurements or exact timing guarantees.

What the owned proxy lab observed

Check JDK HttpClient OkHttp 4.12.0
Direct and authenticated HTTP 200; distinct actual routes 200; distinct actual routes
Missing / wrong HTTP credentials 407 / IOException 407 / 407
Missing / wrong CONNECT credentials 407 / IOException IOException / IOException
Approved CA and valid CONNECT auth 200 with explicit Basic policy opt-in 200 with proxy callback
Untrusted / wrong-hostname certificates SSLHandshakeException SSLHandshakeException / SSLPeerUnverifiedException
Redirect / incomplete body 302 without following / TimeoutException 302 without following / InterruptedIOException

All 27 checks passed against owned loopback fixtures. Rejected authentication produced no destination request. Successful requests correlated destination sockets with proxy upstream sockets, and the destination received no Proxy-Authorization header. The fixtures used random disposable credentials. No commercial endpoint, public exit location, anonymity, speed or uptime was tested.

Diagnose the layer before retrying

A 407 or rejected CONNECT belongs to the proxy layer; destination 401/403 belongs elsewhere. In this helper, status zero means no response status was exposed. Different challenge sequences and client versions can produce different exception shapes, so inspect proxy-side evidence instead of searching only for a literal 407 in application output.

The diagnostic prints selected status, exception class and timing fields, without endpoints, credentials or response bodies. Keep raw errors, HTTP traces and environment dumps out of shared logs. It buffers a small response for diagnosis; add a body-size limit before adapting it to untrusted responses. For a service, reuse clients and choose its redirect/retry policy deliberately.

Continue with Developer Guides, command-line cURL, TLS and route testing methodology, and the troubleshooting checklist.

Versioned Java source files

Use the Java folder in the public source repository for the example, setup instructions, exact dependency versions and a sanitized test summary. The repository is a dated snapshot of owned examples; its loopback checks do not certify a commercial endpoint or every application configuration.