Guide complet des proxies HTTP en Java : HttpClient, OkHttp, Jsoup et Apache

Apprenez à configurer et utiliser des proxies HTTP en Java avec HttpClient (Java 11+), OkHttp, Jsoup et Apache HttpClient. Exemples de code prêts pour la production avec authentification, pooling et parallélisme.

Guide complet des proxies HTTP en Java : HttpClient, OkHttp, Jsoup et Apache

Pourquoi utiliser un proxy HTTP en Java

Les développeurs Java ont souvent besoin de proxies HTTP pour des cas d'usage critiques : scraping web à grande échelle, tests d'API géo-restreintes, monitoring de prix concurrentiel, ou contournement des limitations de taux. Sans proxy approprié, vos requêtes échouent, se font bloquer, ou révèlent votre infrastructure.

Ce guide couvre les quatre principales approches pour utiliser des proxies HTTP en Java moderne :

  • Java 11+ HttpClient — l'API standard avec ProxySelector et Authenticator
  • OkHttp — le client HTTP le plus populaire de l'écosystème JVM
  • Jsoup — parsing HTML avec support proxy intégré
  • Apache HttpClient — pour les systèmes legacy encore répandus

Nous aborderons également le parallélisme avec ExecutorService, la gestion TLS, et les patterns de production (retry, timeouts, connection pooling).

Java 11+ HttpClient avec ProxySelector

L'API java.net.http.HttpClient introduite dans Java 11 offre une approche moderne et réactive. La configuration proxy passe par ProxySelector et l'authentification par Authenticator.

Configuration basique avec proxy HTTP

Pour un proxy sans authentification, utilisez ProxySelector.of() avec un InetSocketAddress :

import java.net.InetSocketAddress;
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 BasicProxyExample {
    
    public static void main(String[] args) throws Exception {
        // Proxy HTTP sur gate.proxyhat.com:8080
        var proxyAddress = new InetSocketAddress("gate.proxyhat.com", 8080);
        var proxySelector = ProxySelector.of(proxyAddress);
        
        var client = HttpClient.newBuilder()
            .proxy(proxySelector)
            .connectTimeout(Duration.ofSeconds(10))
            .followRedirects(HttpClient.Redirect.NORMAL)
            .build();
        
        var request = HttpRequest.newBuilder()
            .uri(URI.create("https://httpbin.org/ip"))
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();
        
        var response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println("Status: " + response.statusCode());
        System.out.println("Body: " + response.body());
    }
}

Proxy authentifié avec Authenticator

Les proxies résidentiels et mobiles nécessitent une authentification. Authenticator fournit les credentials à la demande :

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 AuthenticatedProxyExample {
    
    private static final String PROXY_HOST = "gate.proxyhat.com";
    private static final int PROXY_PORT = 8080;
    private static final String USERNAME = "user-country-FR";  // Geo-targeting France
    private static final String PASSWORD = "your_password";
    
    public static void main(String[] args) throws Exception {
        var proxyAddress = new InetSocketAddress(PROXY_HOST, PROXY_PORT);
        var proxySelector = ProxySelector.of(proxyAddress);
        
        // Authenticator pour l'authentification proxy
        var authenticator = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // Vérifier que c'est bien une demande du proxy
                if (getRequestorType() == RequestorType.PROXY) {
                    return new PasswordAuthentication(USERNAME, PASSWORD.toCharArray());
                }
                return null;
            }
        };
        
        var client = HttpClient.newBuilder()
            .proxy(proxySelector)
            .authenticator(authenticator)
            .connectTimeout(Duration.ofSeconds(15))
            .build();
        
        var request = HttpRequest.newBuilder()
            .uri(URI.create("https://httpbin.org/ip"))
            .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
            .GET()
            .build();
        
        var response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println("IP vue par le serveur: " + response.body());
    }
}

Proxy SOCKS5 avec HttpClient

Pour SOCKS5, utilisez le port 1080 et créez un ProxySelector personnalisé :

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.util.List;
import java.net.http.HttpClient;

public class Socks5ProxySelector extends ProxySelector {
    
    private final InetSocketAddress proxyAddress;
    
    public Socks5ProxySelector(String host, int port) {
        this.proxyAddress = new InetSocketAddress(host, port);
    }
    
    @Override
    public List<Proxy> select(URI uri) {
        return List.of(new Proxy(Proxy.Type.SOCKS, proxyAddress));
    }
    
    @Override
    public void connectFailed(URI uri, java.net.SocketAddress sa, IOException e) {
        System.err.println("Connexion SOCKS échouée: " + uri + " - " + e.getMessage());
    }
}

// Usage
var socksSelector = new Socks5ProxySelector("gate.proxyhat.com", 1080);
var client = HttpClient.newBuilder()
    .proxy(socksSelector)
    .authenticator(authenticator)
    .build();

OkHttp avec proxy et authentification

OkHttp reste le client HTTP le plus utilisé sur la JVM. Sa gestion des proxies est explicite via Proxy et Authenticator.

Configuration OkHttp avec proxy authentifié

import okhttp3.Authenticator;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class OkHttpProxyExample {
    
    private static final String PROXY_HOST = "gate.proxyhat.com";
    private static final int PROXY_PORT = 8080;
    
    public static void main(String[] args) throws Exception {
        // Proxy HTTP
        var proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT));
        
        // Authenticator pour le proxy
        Authenticator proxyAuthenticator = new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) {
                if (response.request().header("Proxy-Authorization") != null) {
                    return null; // Échec d'authentification, abandonner
                }
                String credential = Credentials.basic("user-country-US", "your_password");
                return response.request().newBuilder()
                    .header("Proxy-Authorization", credential)
                    .build();
            }
        };
        
        var client = new OkHttpClient.Builder()
            .proxy(proxy)
            .proxyAuthenticator(proxyAuthenticator)
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .build();
        
        var request = new Request.Builder()
            .url("https://httpbin.org/headers")
            .header("User-Agent", "Mozilla/5.0")
            .build();
        
        try (var response = client.newCall(request).execute()) {
            System.out.println("Status: " + response.code());
            System.out.println("Body: " + response.body().string());
        }
    }
}

Connection pooling et retry avec OkHttp

OkHttp gère automatiquement le connection pooling. Configurez-le pour des workloads intensifs :

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import java.util.concurrent.TimeUnit;

public class OptimizedOkHttpClient {
    
    public static OkHttpClient createPooledClient() {
        var connectionPool = new ConnectionPool(
            50,     // max idle connections
            5,      // keep-alive duration
            TimeUnit.MINUTES
        );
        
        return new OkHttpClient.Builder()
            .proxy(new Proxy(Proxy.Type.HTTP, 
                new InetSocketAddress("gate.proxyhat.com", 8080)))
            .proxyAuthenticator((route, response) -> {
                String credential = Credentials.basic("user-country-DE", "password");
                return response.request().newBuilder()
                    .header("Proxy-Authorization", credential)
                    .build();
            })
            .connectionPool(connectionPool)
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            // Interceptor pour logging en développement
            .addInterceptor(chain -> {
                long start = System.nanoTime();
                var request = chain.request();
                System.out.printf("[%s] %s%n", request.method(), request.url());
                return chain.proceed(request);
            })
            .build();
    }
}

Jsoup avec support proxy pour parsing HTML

Jsoup simplifie l'extraction de données HTML. Il supporte les proxies via Proxy ou la configuration système.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.net.InetSocketAddress;
import java.net.Proxy;

public class JsoupProxyExample {
    
    private static final String PROXY_HOST = "gate.proxyhat.com";
    private static final int PROXY_PORT = 8080;
    
    public static void main(String[] args) throws Exception {
        // Créer le proxy HTTP
        var proxy = new Proxy(Proxy.Type.HTTP, 
            new InetSocketAddress(PROXY_HOST, PROXY_PORT));
        
        // Jsoup avec authentification proxy via headers
        String auth = java.util.Base64.getEncoder()
            .encodeToString(("user-country-FR:your_password").getBytes());
        
        Document doc = Jsoup.connect("https://example.com/products")
            .proxy(proxy)
            .header("Proxy-Authorization", "Basic " + auth)
            .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
            .timeout(30000)
            .followRedirects(true)
            .get();
        
        // Extraction des données
        Elements products = doc.select(".product-item");
        for (Element product : products) {
            String name = product.select("h3.product-name").text();
            String price = product.select(".price").text();
            String link = product.select("a").attr("abs:href");
            
            System.out.printf("Produit: %s | Prix: %s | URL: %s%n", name, price, link);
        }
    }
}

Pattern réutilisable pour scraping avec Jsoup

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.net.Proxy;
import java.util.Optional;

public class JsoupScraper {
    
    private final Proxy proxy;
    private final String proxyAuth;
    
    public JsoupScraper(String proxyHost, int proxyPort, 
                        String username, String password) {
        this.proxy = new Proxy(Proxy.Type.HTTP, 
            new InetSocketAddress(proxyHost, proxyPort));
        this.proxyAuth = java.util.Base64.getEncoder()
            .encodeToString((username + ":" + password).getBytes());
    }
    
    public Optional<Document> fetchDocument(String url, int timeoutMs) {
        try {
            return Optional.of(Jsoup.connect(url)
                .proxy(proxy)
                .header("Proxy-Authorization", "Basic " + proxyAuth)
                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
                .timeout(timeoutMs)
                .maxBodySize(10 * 1024 * 1024)  // 10 MB max
                .get());
        } catch (Exception e) {
            System.err.println("Erreur fetch " + url + ": " + e.getMessage());
            return Optional.empty();
        }
    }
    
    public Optional<Document> fetchWithRetry(String url, int maxRetries) {
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            var doc = fetchDocument(url, 30000);
            if (doc.isPresent()) return doc;
            
            try {
                Thread.sleep(1000 * attempt);  // Backoff exponentiel
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return Optional.empty();
            }
        }
        return Optional.empty();
    }
}

Apache HttpClient (legacy mais toujours pertinent)

De nombreux systèmes d'entreprise utilisent encore Apache HttpClient. Voici la configuration proxy :

import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.routing.HttpRoute;
import org.apache.hc.core5.http.HttpHost;

import java.net.URI;

public class ApacheHttpClientProxyExample {
    
    public static void main(String[] args) throws Exception {
        // Connection pooling
        var connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(100);
        connManager.setDefaultMaxPerRoute(20);
        
        // Configuration proxy
        var proxyHost = new HttpHost("http", "gate.proxyhat.com", 8080);
        
        // Credentials pour le proxy
        var credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
            new AuthScope(proxyHost),
            new UsernamePasswordCredentials("user-country-GB", "password".toCharArray())
        );
        
        try (CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connManager)
            .setProxy(proxyHost)
            .setDefaultCredentialsProvider(credentialsProvider)
            .build()) {
            
            var request = new HttpGet("https://httpbin.org/ip");
            var response = client.execute(request);
            
            String body = new String(response.getEntity().getContent().readAllBytes());
            System.out.println("Response: " + body);
        }
    }
}

Scraping parallèle avec ExecutorService et pool de proxies

Pour des workloads intensifs, combinez ExecutorService avec un pool de proxies résidentiels rotatifs :

import java.net.InetSocketAddress;
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;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ParallelScraper {
    
    private static final String PROXY_HOST = "gate.proxyhat.com";
    private static final int PROXY_PORT = 8080;
    private static final String USERNAME_TEMPLATE = "user-country-%s-session-%s";
    private static final String PASSWORD = "your_password";
    
    private final HttpClient baseClient;
    private final ExecutorService executor;
    private final AtomicInteger sessionCounter = new AtomicInteger(0);
    
    public ParallelScraper(int threadCount) {
        this.executor = Executors.newFixedThreadPool(threadCount);
        
        // Client de base - le proxy sera configuré par requête
        this.baseClient = HttpClient.newBuilder()
            .executor(executor)
            .connectTimeout(Duration.ofSeconds(15))
            .followRedirects(HttpClient.Redirect.NORMAL)
            .build();
    }
    
    private HttpClient createClientWithSession(String country) {
        String username = String.format(USERNAME_TEMPLATE, country, 
            sessionCounter.getAndIncrement());
        
        var proxySelector = ProxySelector.of(
            new InetSocketAddress(PROXY_HOST, PROXY_PORT)
        );
        
        var authenticator = new java.net.Authenticator() {
            @Override
            protected java.net.PasswordAuthentication getPasswordAuthentication() {
                return new java.net.PasswordAuthentication(username, PASSWORD.toCharArray());
            }
        };
        
        return HttpClient.newBuilder()
            .proxy(proxySelector)
            .authenticator(authenticator)
            .connectTimeout(Duration.ofSeconds(15))
            .build();
    }
    
    public CompletableFuture<List<String>> scrapeUrls(List<String> urls, String country) {
        List<CompletableFuture<String>> futures = urls.stream()
            .map(url -> scrapeWithRetry(url, country, 3))
            .toList();
        
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
            .thenApply(v -> futures.stream()
                .map(CompletableFuture::join)
                .toList());
    }
    
    private CompletableFuture<String> scrapeWithRetry(String url, String country, int maxRetries) {
        return scrapeWithRetryInternal(url, country, maxRetries, 0);
    }
    
    private CompletableFuture<String> scrapeWithRetryInternal(
            String url, String country, int maxRetries, int attempt) {
        
        var client = createClientWithSession(country);
        var request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();
        
        return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .handle((response, ex) -> {
                if (ex != null || response.statusCode() >= 500) {
                    if (attempt < maxRetries) {
                        System.err.printf("Retry %d/%d for %s%n", attempt + 1, maxRetries, url);
                        try {
                            Thread.sleep(1000L * (attempt + 1));  // Backoff
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                        return scrapeWithRetryInternal(url, country, maxRetries, attempt + 1);
                    }
                    return CompletableFuture.completedFuture("ERROR: " + url);
                }
                return CompletableFuture.completedFuture(
                    response.statusCode() + ":" + response.body().substring(0, Math.min(100, response.body().length()))
                );
            })
            .thenCompose(cf -> cf);
    }
    
    public void shutdown() {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
        }
    }
    
    public static void main(String[] args) throws Exception {
        var scraper = new ParallelScraper(10);
        
        var urls = List.of(
            "https://httpbin.org/ip",
            "https://httpbin.org/headers",
            "https://httpbin.org/user-agent",
            "https://httpbin.org/get"
        );
        
        try {
            var results = scraper.scrapeUrls(urls, "US").join();
            results.forEach(System.out::println);
        } finally {
            scraper.shutdown();
        }
    }
}

Considérations TLS et SSLContext personnalisé

Certains proxies effectent du TLS interception (man-in-the-middle). D'autres serveurs utilisent des certificats auto-signés. Java JSSE permet de personnaliser la validation :

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.http.HttpClient;
import java.security.cert.X509Certificate;

public class TlsConfig {
    
    // ATTENTION: Ne jamais utiliser en production sans validation
    // Crée un SSLContext qui ignore la validation des certificats
    // Utile pour les tests ou les environnements avec proxies interceptants
    
    public static SSLContext createTrustAllContext() throws Exception {
        var trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {}
            
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}
            
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        
        var sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        return sslContext;
    }
    
    // Version sécurisée avec TrustStore personnalisé
    public static SSLContext createCustomTrustStore(String trustStorePath, 
                                                     String trustStorePassword) throws Exception {
        var trustStore = java.security.KeyStore.getInstance("JKS");
        try (var is = java.nio.file.Files.newInputStream(java.nio.file.Path.of(trustStorePath))) {
            trustStore.load(is, trustStorePassword.toCharArray());
        }
        
        var trustManagerFactory = javax.net.ssl.TrustManagerFactory.getInstance(
            javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()
        );
        trustManagerFactory.init(trustStore);
        
        var sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
        return sslContext;
    }
    
    public static HttpClient createClientWithCustomSsl(SSLContext sslContext) {
        return HttpClient.newBuilder()
            .sslContext(sslContext)
            .sslParameters(new javax.net.ssl.SSLParameters())
            .connectTimeout(java.time.Duration.ofSeconds(15))
            .build();
    }
}

Configuration TLS avec OkHttp

import okhttp3.OkHttpClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

public class OkHttpTlsConfig {
    
    public static OkHttpClient createTrustAllClient() throws Exception {
        var trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {}
            
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}
            
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        
        var sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new javax.net.ssl.TrustManager[]{trustManager}, null);
        
        return new OkHttpClient.Builder()
            .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
            .hostnameVerifier((hostname, session) -> true)
            .build();
    }
}

Bonnes pratiques et patterns de production

Gestion des timeouts

Configurez systématiquement des timeouts pour éviter les threads bloqués :

Timeout Valeur recommandée Description
Connection 10-15 secondes Établissement de la connexion TCP
Read 30-60 secondes Lecture des données
Write 30 secondes Envoi des données
Request 60-120 secondes Timeout global de la requête

Retry avec circuit breaker

Implémentez un pattern retry avec exponential backoff et circuit breaker pour les APIs instables :

import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

public class RetryPolicy {
    
    private final int maxAttempts;
    private final Duration initialDelay;
    private final Duration maxDelay;
    private final double backoffMultiplier;
    
    public RetryPolicy(int maxAttempts, Duration initialDelay, 
                       Duration maxDelay, double backoffMultiplier) {
        this.maxAttempts = maxAttempts;
        this.initialDelay = initialDelay;
        this.maxDelay = maxDelay;
        this.backoffMultiplier = backoffMultiplier;
    }
    
    public <T> T execute(Supplier<T> action) {
        Exception lastException = null;
        
        for (int attempt = 1; attempt <= maxAttempts; attempt++) {
            try {
                return action.get();
            } catch (Exception e) {
                lastException = e;
                
                if (attempt == maxAttempts) break;
                
                long delayMs = (long) Math.min(
                    initialDelay.toMillis() * Math.pow(backoffMultiplier, attempt - 1),
                    maxDelay.toMillis()
                );
                
                System.err.printf("Tentative %d échouée, retry dans %dms: %s%n",
                    attempt, delayMs, e.getMessage());
                
                try {
                    Thread.sleep(delayMs);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("Interrupted pendant retry", ie);
                }
            }
        }
        
        throw new RuntimeException("Échec après " + maxAttempts + " tentatives", lastException);
    }
    
    // Usage
    public static void main(String[] args) {
        var policy = new RetryPolicy(3, Duration.ofSeconds(1), Duration.ofSeconds(30), 2.0);
        
        String result = policy.execute(() -> {
            // Appel HTTP ici
            return "success";
        });
        
        System.out.println(result);
    }
}

Points clés à retenir

  • Java 11+ HttpClient offre une API moderne avec ProxySelector et Authenticator — idéal pour les nouveaux projets.
  • OkHttp reste le choix le plus robuste pour la production avec connection pooling automatique et retry intégré.
  • Jsoup permet le parsing HTML direct avec proxy — parfait pour le scraping simple.
  • Toujours configurer des timeouts explicites pour éviter les blocages.
  • Utiliser des sessions sticky (user-session-xxx) pour les requêtes nécessitant la même IP.
  • Implémenter un retry avec exponential backoff pour la résilience.
  • Attention au TLS interception par certains proxies — configurez SSLContext si nécessaire.

Conclusion

L'utilisation de proxies HTTP en Java nécessite de choisir le bon client selon vos besoins : HttpClient pour les projets Java modernes, OkHttp pour la robustesse production, Jsoup pour le scraping HTML simple. Configurez systématiquement l'authentification, les timeouts, et implémentez des stratégies de retry pour des applications fiables.

Pour des workloads intensifs, le parallélisme avec ExecutorService combiné à un pool de proxies résidentiels rotatifs offre les meilleures performances. Consultez notre page de tarification pour les options de proxies résidentiels et mobiles adaptées à votre cas d'usage.

Prêt à commencer ?

Accédez à plus de 50M d'IPs résidentielles dans plus de 148 pays avec filtrage IA.

Voir les tarifsProxies résidentiels
← Retour au Blog