Si vous développez des scrapers, des clients API ou des applications Android en Kotlin, vous avez probablement rencontré des blocages IP, des erreurs 403 ou des CAPTCHAs inattendus. Utiliser des proxies en Kotlin est la solution pour distribuer vos requêtes à travers plusieurs adresses IP, contourner les limites de taux et accéder à des contenus géo-restreints. Ce guide pratique vous montre comment configurer Ktor Client et OkHttp avec des proxies résidentiels, datacenter et mobiles — avec du code exécutable à chaque étape.
Pourquoi utiliser des proxies en Kotlin ?
Les serveurs web modernes utilisent des systèmes anti-bot sophistiqués qui analysent l'adresse IP source, les en-têtes HTTP, le fingerprint TLS et le comportement de navigation. Quand vous envoyez des centaines de requêtes depuis une seule IP, ces systèmes déclenchent des blocages, des CAPTCHAs ou des réponses 429 (Too Many Requests).
Un proxy agit comme un intermédiaire : votre client Kotlin se connecte au proxy, qui relaie la requête vers la cible. L'IP vue par le serveur cible est celle du proxy, pas la vôtre. En rotant à travers un pool de proxies résidentiels, vous distribuez vos requêtes sur des centaines d'IPs différentes, rendant chaque requête indiscernable du trafic d'un utilisateur réel.
Le Kotlin web scraping nécessite donc une stratégie proxy adaptée à la cible. Voici une comparaison des trois types de proxies disponibles chez ProxyHat :
| Type de proxy | Avantages | Inconvénients | Cas d'usage typique |
|---|---|---|---|
| Résidentiel | IPs d'ISP réelles, faible détection, ~99.9% de succès sur cibles strictes | Latence ~200ms supérieure vs datacenter, coût plus élevé | SERP scraping, réseaux sociaux, e-commerce |
| Datacenter | Rapide (<50ms), économique, idéal pour haut volume | ASNs facilement détectables par les anti-bots | APIs publiques, tests, monitoring interne |
| Mobile | Détection quasi nulle, IPs 4G/5G d'opérateurs | Le plus coûteux, latence variable | Cibles très strictes, comptes sensibles |
Pour approfondir les cas d'usage, consultez notre guide sur le web scraping avec proxies et le tracking SERP.
Configuration du projet — Ktor Client et OkHttp
Kotlin offre deux clients HTTP majeurs pour le scraping : Ktor Client (multiplateforme, coroutine-native) et OkHttp (standard Android/JVM). Les deux supportent les proxies HTTP et SOCKS5, mais l'API diffère.
Dépendances Gradle
Pour un projet Kotlin/JVM ou Android, ajoutez ces dépendances dans votre build.gradle.kts :
// Ktor 3.x avec moteur CIO (Coroutine-based, pas de dépendance native)
implementation("io.ktor:ktor-client-core:3.0.3")
implementation("io.ktor:ktor-client-cio:3.0.3")
// OkHttp 4.x (standard Android/JVM)
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Coroutines pour la concurrence
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
Le moteur CIO de Ktor est purement Kotlin, basé sur coroutines, et ne nécessite aucune dépendance native. Il supporte les proxies HTTP via java.net.Proxy.
Ktor HttpClient avec proxy HTTP
Configuration basique d'un Ktor client proxy sur le port 8080 :
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import java.net.InetSocketAddress
import java.net.Proxy
val client = HttpClient(CIO) {
engine {
proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("gate.proxyhat.com", 8080))
}
}
// Test basique
val response: HttpResponse = client.get("https://httpbin.org/ip")
println(response.bodyAsText())
client.close()
OkHttp avec proxy — baseline
Configuration équivalente avec OkHttp :
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.InetSocketAddress
import java.net.Proxy
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("gate.proxyhat.com", 8080))
val client = OkHttpClient.Builder()
.proxy(proxy)
.build()
val request = Request.Builder()
.url("https://httpbin.org/ip")
.build()
client.newCall(request).execute().use { response ->
if (response.isSuccessful) {
println(response.body?.string())
}
}
Sans authentification, ces deux exemples échoueront avec une erreur 407 Proxy Authentication Required. C'est là que les choses deviennent intéressantes.
Routage via gate.proxyhat.com : geo-targeting et sessions sticky
ProxyHat encode le geo-targeting et les sessions sticky directement dans le nom d'utilisateur. Le format est user-country-XX-city-YYYY-session-ZZZ. L'authentification proxy se fait via l'en-tête Proxy-Authorization: Basic, mais comme l'authentification proxy est spécifique au moteur HTTP, Ktor ne l'envoie pas automatiquement — il faut l'ajouter manuellement dans defaultRequest.
Voici un exemple complet avec geo-targeting (Allemagne, Berlin) et session sticky :
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.Base64
// Geo-targeting: Allemagne, Berlin + session sticky
val username = "user-country-DE-city-berlin-session-abc123"
val password = "your-password"
val credentials = Base64.getEncoder()
.encodeToString("$username:$password".toByteArray())
val client = HttpClient(CIO) {
engine {
proxy = Proxy(
Proxy.Type.HTTP,
InetSocketAddress("gate.proxyhat.com", 8080)
)
}
defaultRequest {
header("Proxy-Authorization", "Basic $credentials")
header("User-Agent", "Mozilla/5.0 (compatible; MyBot/1.0)")
}
}
val response: HttpResponse = client.get("https://httpbin.org/headers")
println(response.bodyAsText())
client.close()
Points clés du geo-targeting :
user-country-DE— route via une IP allemandecity-berlin— cible une IP à Berlin (plus précis, légèrement plus lent)session-abc123— sticky session : toutes les requêtes utilisent la même IP tant que la session est active
Sans le flag session, ProxyHat attribue une nouvelle IP à chaque requête (rotation per-request). Pour du scraping SERP où vous devez paginer des résultats, la session sticky est essentielle pour maintenir la cohérence de l'IP source. Consultez les docs ProxyHat pour la liste complète des paramètres supportés.
Le SDK ProxyHat reproduit ce même pattern : il construit l'URL du proxy avec les flags geo/session dans le username et injecte l'en-tête Proxy-Authorization automatiquement. En Kotlin, vous pouvez soit utiliser le SDK, soit reproduire ce pattern manuellement comme ci-dessus.
SOCKS5 sur le port 1080
Le protocole SOCKS5 opère au niveau TCP, ce qui le rend utile pour les connexions non-HTTP (WebSockets, gRPC, connexions brutes). ProxyHat expose SOCKS5 sur le port 1080.
En JVM, l'approche la plus simple pour OkHttp proxy authentication en SOCKS5 consiste à utiliser les propriétés système java.net.socks.username et java.net.socks.password :
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.InetSocketAddress
import java.net.Proxy
// Configuration SOCKS5 via propriétés système
System.setProperty("socksProxyHost", "gate.proxyhat.com")
System.setProperty("socksProxyPort", "1080")
System.setProperty("java.net.socks.username", "user-country-FR")
System.setProperty("java.net.socks.password", "your-password")
val client = OkHttpClient.Builder()
.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress("gate.proxyhat.com", 1080)))
.build()
val request = Request.Builder()
.url("https://httpbin.org/ip")
.build()
client.newCall(request).execute().use { response ->
println(response.body?.string())
}
Attention : les propriétés système sont globales à la JVM. En Android ou dans un service multi-tenant, préférez l'authentification par en-tête Proxy-Authorization avec HTTP sur le port 8080 pour éviter les conflits.
Proxies résidentiels pour cibles sociales et applicatives
Les plateformes sociales (Instagram, Twitter/X, LinkedIn) et les apps e-commerce détectent et bloquent les ASNs datacenter (AWS, Google Cloud, DigitalOcean) en quelques requêtes. Les proxies résidentiels utilisent des IPs d'ISP réelles (Orange, Comcast, Vodafone), ce qui rend le trafic indiscernable d'un utilisateur normal.
Pour du Kotlin web scraping à grande échelle, vous devez combiner proxies résidentiels, rotation de sessions et contrôle de concurrence. Voici un exemple complet utilisant les coroutines Kotlin avec async/awaitAll et un Semaphore pour limiter le parallélisme à 100 requêtes concurrentes :
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.Base64
suspend fun scrapeConcurrent(
urls: List<String>,
maxConcurrency: Int = 100
): List<Result<String>> {
val semaphore = Semaphore(maxConcurrency)
val credentials = Base64.getEncoder()
.encodeToString("user-country-US:your-password".toByteArray())
val client = HttpClient(CIO) {
engine {
proxy = Proxy(
Proxy.Type.HTTP,
InetSocketAddress("gate.proxyhat.com", 8080)
)
}
defaultRequest {
header("Proxy-Authorization", "Basic $credentials")
}
}
return coroutineScope {
urls.map { url ->
async(Dispatchers.IO) {
semaphore.withPermit {
try {
val resp = client.get(url)
Result.success(resp.bodyAsText())
} catch (e: Exception) {
Result.failure(e)
}
}
}
}.awaitAll()
}.also { client.close() }
}
Pourquoi le Semaphore ? Sans contrôle de concurrence, async lance toutes les coroutines simultanément. Sur 10 000 URLs, cela créerait 10 000 connexions simultanées — le proxy rejeterait la plupart. Le Semaphore(100) garantit qu'au maximum 100 requêtes sont en vol à tout moment.
Rotation per-request vs sticky : sans le flag session, ProxyHat attribue une nouvelle IP résidentielle à chaque requête. C'est idéal pour le scraping massif. Pour les sessions de connexion (login + navigation), utilisez session-xxx pour garder la même IP pendant toute la session.
Hardening production — Authenticator, retries, TLS
En production, plusieurs problèmes surviennent : expirations de session proxy, timeouts réseau, challenges 407 inattendus, et pools de connexions saturés. Voici une configuration OkHttp durcie avec proxyAuthenticator pour gérer les 407, timeouts explicites, et pool de connexions :
import okhttp3.*
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.Base64
import java.util.concurrent.TimeUnit
val username = "user-country-US-session-mySession01"
val password = "your-password"
val credentials = Base64.getEncoder()
.encodeToString("$username:$password".toByteArray())
// Authenticator pour les challenges 407 Proxy Authentication Required
val proxyAuth = Authenticator { _, response ->
if (response.code == 407) {
response.request.newBuilder()
.header("Proxy-Authorization", "Basic $credentials")
.build()
} else null
}
val client = OkHttpClient.Builder()
.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("gate.proxyhat.com", 8080)))
.proxyAuthenticator(proxyAuth)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.connectionPool(ConnectionPool(20, 5, TimeUnit.MINUTES))
.build()
val request = Request.Builder()
.url("https://httpbin.org/ip")
.header("User-Agent", "Mozilla/5.0 (compatible; MyBot/1.0)")
.build()
client.newCall(request).execute().use { response ->
println("Status: ${response.code}")
println(response.body?.string())
}
Détails de configuration :
connectTimeout(10s)— évite de bloquer indéfiniment si le proxy ne répond pasreadTimeout(30s)— les cibles lentes (pages lourdes, APIs lentes) ont besoin de margeConnectionPool(20, 5min)— 20 connexions keep-alive, 5 minutes de TTL. Réduit la latence de connexion de ~200ms à ~0ms sur les requêtes répétéesretryOnConnectionFailure(true)— OkHttp retente automatiquement les échecs réseauproxyAuthenticator— gère les challenges 407 en réinjectant l'en-têteProxy-Authorization
Configuration TLS
Par défaut, Ktor et OkHttp utilisent la configuration TLS de la JVM. Pour éviter les erreurs de certificat avec certains proxies, vous pouvez explicitement configurer un TrustManager standard :
import okhttp3.OkHttpClient
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
// ATTENTION: à n'utiliser qu'en dev/test. En production,
// gardez la validation TLS par défaut de la JVM.
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
})
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
val client = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
.hostnameVerifier { _, _ -> true }
.build()
En production, ne désactivez jamais la validation TLS. ProxyHat utilise des certificats valides sur gate.proxyhat.com. La configuration ci-dessus est uniquement pour le débogage.
Note Android : NetworkSecurityConfig
Sur Android 9+ (API 28+), le trafic HTTP en clair est bloqué par défaut. Pour autoriser la connexion au proxy (qui est en HTTP, pas HTTPS), ajoutez un network_security_config.xml :
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">gate.proxyhat.com</domain>
</domain-config>
</network-security-config>
Puis référencez-le dans le AndroidManifest.xml :
<application
android:networkSecurityConfig="@xml/network_security_config">
...
</application>
Cela autorise uniquement le trafic en clair vers gate.proxyhat.com tout en gardant le HTTPS obligatoire pour le reste. Le tunnel proxy lui-même est en HTTP, mais le trafic entre le proxy et la cible reste chiffré en HTTPS.
Considérations éthiques et légales
Le scraping web n'est pas illégal per se, mais il opère dans une zone grise. Voici les principes à respecter :
- Données publiques uniquement. Ne scrapez que des pages accessibles sans authentification. Accéder à des données derrière un login sans autorisation peut violer le Computer Fraud and Abuse Act (CFAA) aux États-Unis ou des lois équivalentes en Europe.
- GDPR dans l'UE. Le scraping de données personnelles (noms, emails, photos) est soumis au Règlement Général sur la Protection des Données (RGPD). Vous devez avoir une base légale pour chaque traitement.
- Respectez
robots.txtet les conditions d'utilisation. Unrobots.txtn'est pas juridiquement contraignant, mais l'ignorer renforce l'argument de « accès non autorisé » dans une procédure judiciaire. - Préférez les APIs officielles. Si une plateforme offre une API (Twitter API, Google Custom Search, Amazon Product Advertising), utilisez-la. Le scraping doit être un dernier recours.
- Limitez votre impact. Ne submergez pas les serveurs cibles. Un délai de 1 à 5 secondes entre les requêtes est une bonne pratique. Le
Semaphoreci-dessus limite la concurrence ; ajoutez desdelay()pour espacer les requêtes.
Pour les tarifs des différents types de proxies, consultez notre page de tarification.
Points clés à retenir
Utiliser des proxies en Kotlin se résume à quatre étapes : (1) configurer le proxy dans le moteur HTTP (Ktor CIO ou OkHttp), (2) ajouter l'en-tête
Proxy-Authorization: Basicavec les credentials encodés, (3) encoder le geo-targeting et les sessions sticky dans le username, et (4) contrôler la concurrence avecSemaphoreetasync/awaitAll. Pour la production, ajoutez unproxyAuthenticatorOkHttp pour gérer les 407, des timeouts explicites, et un pool de connexions. Préférez les proxies résidentiels pour les cibles strictes, datacenter pour le volume, et mobile pour les anti-bots les plus agressifs.
FAQ
Qu'est-ce que l'utilisation de proxies en Kotlin ?
L'utilisation de proxies en Kotlin consiste à router les requêtes HTTP ou SOCKS5 d'une application Kotlin (backend, Android ou multiplateforme) via un serveur intermédiaire. Avec Ktor Client, on configure le proxy au niveau du moteur (CIO, OkHttp, etc.) via java.net.Proxy. Avec OkHttp, on utilise OkHttpClient.Builder().proxy(...). L'authentification se fait via l'en-tête Proxy-Authorization: Basic ou les propriétés système SOCKS.
Pourquoi utiliser des proxies en Kotlin est-il important ?
Les systèmes anti-bot modernes bloquent les IPs datacenter, limitent le débit par IP, et servent du contenu géo-restreint. Sans proxy, un scraper Kotlin envoyant 1000 requêtes depuis une seule IP sera bloqué en quelques minutes. Les proxies résidentiels distribuent le trafic sur des IPs d'ISP réelles, contournant ces limitations et offrant un taux de succès de ~99.9% sur les cibles strictes comme les SERP Google ou les réseaux sociaux.
Quel type de proxy fonctionne le mieux en Kotlin ?
Cela dépend de la cible. Les proxies résidentiels sont idéaux pour les plateformes sociales, le SERP scraping et l'e-commerce (IPs d'ISP, faible détection). Les proxies datacenter sont plus rapides (<50ms) et économiques, adaptés aux APIs publiques et aux tests. Les proxies mobiles (4G/5G) offrent la détection la plus faible mais au coût le plus élevé. Pour la plupart des projets de scraping en Kotlin, commencez par des résidentiels avec rotation per-request.
Comment éviter les blocages avec des proxies en Kotlin ?
Utilisez des proxies résidentiels ou mobiles (jamais datacenter pour les cibles strictes), rottez les sessions via le flag session-xxx de ProxyHat, limitez la concurrence avec Semaphore (max 50 à 100 requêtes simultanées), ajoutez des délais aléatoires de 1 à 5 secondes entre les requêtes, configurez des en-têtes réalistes (User-Agent, Accept-Language), et implémentez des retries avec backoff exponentiel. Respectez toujours robots.txt et les conditions d'utilisation de la cible.






