← Kembali ke blog

Python requests: ProxyError, SSLError WRONG_VERSION_NUMBER dan 407 — cara memperbaikinya secara praktis

Analisis mendetail tentang kesalahan umum saat bekerja dengan proxy di Python requests: ProxyError, SSLError WRONG_VERSION_NUMBER, 407 Proxy Authentication Required. Contoh kode yang berfungsi untuk setiap situasi.

📅11 November 2026

Jika Anda melakukan parsing situs atau mengotomatiskan permintaan melalui proxy di Python, cepat atau lambat Anda akan menghadapi tiga kesalahan klasik: ProxyError, SSLError: WRONG_VERSION_NUMBER dan HTTP 407 Proxy Authentication Required. Dalam artikel ini, kita akan membahas penyebab masing-masing dan menunjukkan kode yang berfungsi untuk memperbaikinya.

Cara requests bekerja dengan proxy: sintaks dasar

Perpustakaan requests menerima proxy melalui kamus proxies, di mana kunci adalah skema permintaan (http dan https), dan nilai adalah URL server proxy dengan otorisasi opsional.

import requests

proxies = {
    "http": "http://user:password@proxy_host:port",
    "https": "http://user:password@proxy_host:port",
}

response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(response.json())

Harap dicatat: bahkan untuk permintaan HTTPS, skema proxy biasanya ditentukan sebagai http://, karena sebagian besar server proxy menerima terowongan CONNECT melalui protokol HTTP, bukan membungkusnya dalam SSL. Jika Anda menentukan https:// untuk proxy yang tidak mendukungnya — Anda akan mendapatkan SSLError, yang akan dibahas di bawah.

Jika Anda bekerja dengan proxy SOCKS5, Anda akan memerlukan paket tambahan:

pip install requests[socks]

# Dan sintaks proxies berubah:
proxies = {
    "http": "socks5://user:password@proxy_host:port",
    "https": "socks5://user:password@proxy_host:port",
}

ProxyError: penyebab dan solusi

requests.exceptions.ProxyError adalah pembungkus untuk pengecualian jaringan tingkat rendah yang terjadi saat mencoba membuat koneksi dengan server proxy. Empat skenario paling umum terjadi.

1. Proxy tidak tersedia atau alamat/port salah

requests.exceptions.ProxyError: HTTPSConnectionPool(host='example.com', port=443):
Max retries exceeded with url: / (Caused by ProxyError('Cannot connect to proxy.',
ConnectionResetError(104, 'Connection reset by peer')))

Periksa bahwa host dan port dimasukkan dengan benar, dan server proxy benar-benar aktif. Cara tercepat untuk mendiagnosis — coba sambungkan melalui curl:

curl -x http://user:password@proxy_host:port https://httpbin.org/ip -v

2. Proxy memblokir permintaan Anda (pemblokiran berdasarkan IP atau User-Agent)

Proxy dari pusat data sering kali diblokir oleh situs target karena rentang IP mereka dikenal oleh sistem anti-fraud. Jika kesalahan muncul secara konsisten saat mengakses situs tertentu (misalnya, Wildberries, Ozon, atau media sosial), dan bukan di semua situs sekaligus — masalahnya bukan pada proxy itu sendiri, tetapi pada reputasinya. Dalam kasus ini, beralih ke proxy residensial — mereka menggunakan IP pengguna nyata dan lebih jarang terkena pemblokiran oleh sistem anti-fraud.

3. Batas koneksi bersamaan terlampaui

Jika Anda menjalankan parsing multithread dan membuka ratusan koneksi melalui proxy yang sama, server dapat mulai menolak koneksi yang berlebihan. Solusinya adalah menggunakan pool koneksi melalui requests.adapters.HTTPAdapter dengan batasan pool_maxsize dan max_retries:

from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
retries = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
adapter = HTTPAdapter(max_retries=retries, pool_connections=20, pool_maxsize=20)

session.mount("http://", adapter)
session.mount("https://", adapter)

response = session.get("https://httpbin.org/ip", proxies=proxies, timeout=10)

4. Timeout di sisi server proxy

Jika proxy "tergantung" lebih lama dari timeout yang ditetapkan, Anda akan melihat ProxyError, yang dibungkus dalam ReadTimeoutError. Tingkatkan timeout ke nilai yang wajar (biasanya 15-30 detik sudah cukup) dan tambahkan penanganan pengecualian secara terpisah:

try:
    response = requests.get(url, proxies=proxies, timeout=20)
except requests.exceptions.ProxyError as e:
    print(f"Masalah dengan proxy: {e}")
except requests.exceptions.Timeout:
    print("Proxy tidak menjawab dalam waktu yang ditentukan")

SSLError WRONG_VERSION_NUMBER: analisis masalah

Kesalahan ini adalah salah satu yang paling membingungkan pada pandangan pertama, tetapi pada kenyataannya hampir selalu memiliki satu penyebab.

requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443):
Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL:
WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)')))

WRONG_VERSION_NUMBER berarti bahwa klien mencoba melakukan handshake SSL/TLS di tempat di mana server mengharapkan lalu lintas HTTP biasa (tanpa enkripsi). Penyebabnya biasanya terletak pada skema proxy yang salah ditentukan dalam kamus proxies.

Kesalahan umum: menentukan https:// alih-alih http:// di alamat server proxy. Sebagian besar proxy HTTP(S) menerima koneksi melalui HTTP biasa, bahkan ketika memproksikan lalu lintas HTTPS melalui mekanisme CONNECT.

# SALAH — akan memicu WRONG_VERSION_NUMBER
proxies = {
    "http": "https://user:password@proxy_host:port",
    "https": "https://user:password@proxy_host:port",
}

# BENAR
proxies = {
    "http": "http://user:password@proxy_host:port",
    "https": "http://user:password@proxy_host:port",
}

Penyebab umum kedua adalah port yang secara fisik tidak mendukung TLS. Misalnya, jika penyedia proxy menetapkan port 8080 hanya untuk lalu lintas HTTP, dan Anda mencoba untuk mengatur koneksi TLS langsung (melewati CONNECT), server akan merespons dengan teks biasa alih-alih handshake TLS, dan pustaka klien OpenSSL akan mengeluarkan kesalahan ini. Periksa dokumentasi penyedia proxy Anda untuk melihat port dan protokol (HTTP/HTTPS/SOCKS5) yang tersedia di setiap port yang berbeda.

Pilihan ketiga adalah Anda menggunakan socket atau pustaka pihak ketiga untuk koneksi TCP langsung dengan proxy, melewati mekanisme standar requests. Dalam hal ini, pastikan bahwa pembungkus TLS diterapkan hanya untuk situs target yang sebenarnya, bukan untuk koneksi itu sendiri dengan proxy.

407 Proxy Authentication Required: otorisasi

Kode respons 407 adalah analog dari 401 standar, tetapi untuk server proxy. Ini berarti bahwa server meminta otorisasi, dan Anda tidak memberikannya atau memberikannya dalam format yang salah.

Metode 1: login dan password langsung di URL

proxies = {
    "http": "http://login:password@proxy_host:port",
    "https": "http://login:password@proxy_host:port",
}

response = requests.get("https://httpbin.org/ip", proxies=proxies)

Metode ini adalah yang paling sederhana, tetapi jika login atau password mengandung karakter khusus (misalnya, @, :, /), mereka perlu di-escape menggunakan urllib.parse.quote:

from urllib.parse import quote

login = quote("user@domain")
password = quote("p@ssw:ord!")

proxy_url = f"http://{login}:{password}@proxy_host:port"
proxies = {"http": proxy_url, "https": proxy_url}

Metode 2: header Proxy-Authorization secara manual

Jika penyedia proxy menggunakan skema otorisasi yang tidak standar atau Anda memerlukan lebih banyak kontrol, Anda dapat menyusun header secara manual melalui pengkodean base64:

import base64
import requests

login = "user"
password = "password"
credentials = base64.b64encode(f"{login}:{password}".encode()).decode()

headers = {
    "Proxy-Authorization": f"Basic {credentials}"
}

proxies = {
    "http": "http://proxy_host:port",
    "https": "http://proxy_host:port",
}

response = requests.get(
    "https://httpbin.org/ip",
    proxies=proxies,
    headers=headers,
    timeout=10
)

Penting: beberapa penyedia proxy mengaitkan otorisasi tidak dengan login/password, tetapi dengan IP statis tertentu klien (whitelist). Jika Anda mengubah IP (misalnya, bekerja melalui VPN atau IP dinamis penyedia), kesalahan 407 dapat muncul bahkan dengan kredensial yang benar — karena IP eksternal Anda saat ini tidak terdaftar dalam whitelist di sisi proxy. Solusinya adalah masuk ke akun penyedia dan memperbarui daftar IP yang diizinkan, atau beralih ke otorisasi berdasarkan login/password alih-alih IP-whitelist.

Logika retry dan penanganan pengecualian

Dalam praktiknya, kesalahan proxy jarang bersifat satu kali — terutama saat melakukan parsing massal. Arsitektur kode yang benar harus mempertimbangkan upaya ulang dengan penundaan dan pencatatan setiap kesalahan secara terpisah.

import time
import requests
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def fetch_with_retry(url, proxies, max_retries=3, backoff=2):
    for attempt in range(1, max_retries + 1):
        try:
            response = requests.get(url, proxies=proxies, timeout=15)
            response.raise_for_status()
            return response
        except requests.exceptions.ProxyError as e:
            logger.warning(f"[Upaya {attempt}] ProxyError: {e}")
        except requests.exceptions.SSLError as e:
            logger.warning(f"[Upaya {attempt}] SSLError: {e}")
        except requests.exceptions.HTTPError as e:
            if response.status_code == 407:
                logger.error("407: periksa login/password atau whitelist IP proxy")
                break
            logger.warning(f"[Upaya {attempt}] HTTPError: {e}")
        except requests.exceptions.Timeout:
            logger.warning(f"[Upaya {attempt}] Timeout koneksi")

        time.sleep(backoff * attempt)

    raise RuntimeError(f"Gagal mendapatkan {url} setelah {max_retries} upaya")

Pendekatan ini menghemat jam debugging: alih-alih skrip terjatuh pada gangguan jaringan pertama, Anda mendapatkan log yang jelas dengan menunjukkan jenis kesalahan tertentu pada setiap upaya.

Rotasi proxy dan mengatasi pemblokiran

Jika ProxyError dan 407 sering kali terkait dengan pengaturan kode, maka pemblokiran massal dan penolakan koneksi yang stabil pada domain tertentu hampir selalu menunjukkan masalah dengan kualitas pool IP itu sendiri. Untuk tugas seperti parsing marketplace (Wildberries, Ozon, Avito) atau bekerja dengan media sosial, disarankan untuk melakukan rotasi IP pada setiap permintaan atau melalui interval yang ditentukan.

import random

proxy_pool = [
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
]

def get_random_proxy():
    proxy = random.choice(proxy_pool)
    return {"http": proxy, "https": proxy}

response = requests.get(url, proxies=get_random_proxy(), timeout=15)

Untuk parser produksi, biasanya lebih nyaman menggunakan proxy dengan rotasi otomatis di sisi penyedia — sehingga tidak perlu menyimpan daftar IP sendiri, rotasi terjadi secara transparan melalui satu endpoint. Dalam hal ini, proxy residensial dengan rotasi sangat cocok untuk menghindari perlindungan anti-bot di situs dengan sistem deteksi yang ketat, dan proxy pusat data — pilihan yang baik, jika kecepatan permintaan penting, dan situs target tidak memblokir rentang pusat data secara agresif.

Jenis proxy Kecepatan Risiko pemblokiran Tugas
Pusat data Tinggi Sedang-tinggi Parsing cepat API terbuka
Residen Sedang Rendah Parsing marketplace, media sosial
Mobile Sedang-rendah Minimal Bekerja dengan sistem anti-bot yang ketat

Session, timeout, dan verifikasi SSL

Untuk skrip yang berjalan lama (misalnya, parser siklik), sebaiknya gunakan requests.Session() alih-alih panggilan terpisah requests.get(). Session menggunakan kembali koneksi TCP, yang mengurangi beban pada server proxy dan mengurangi jumlah ProxyError pada volume permintaan yang besar.

session = requests.Session()
session.proxies.update({
    "http": "http://user:password@proxy_host:port",
    "https": "http://user:password@proxy_host:port",
})

for url in urls_list:
    try:
        resp = session.get(url, timeout=15)
        print(resp.status_code, url)
    except requests.exceptions.RequestException as e:
        print(f"Kesalahan di {url}: {e}")

Secara terpisah, perlu disebutkan parameter verify. Jika Anda bekerja dengan proxy yang mengganti sertifikat SSL (proxy MITM untuk debugging atau beberapa proxy perusahaan), requests dapat memberikan peringatan tentang ketidakcocokan sertifikat. Mematikan verifikasi sepenuhnya (verify=False) sebaiknya hanya dilakukan di lingkungan pengujian — di produksi ini menciptakan risiko serangan "man-in-the-middle":

# Hanya untuk debugging lokal!
response = requests.get(url, proxies=proxies, verify=False, timeout=15)

# Cara yang benar — tentukan jalur ke sertifikat proxy yang tepercaya
response = requests.get(url, proxies=proxies, verify="/path/to/proxy_cert.pem")

Checklist diagnosis kesalahan

Jika skrip terjatuh dengan kesalahan proxy, periksa daftar ini dari atas ke bawah — dalam 90% kasus penyebabnya ditemukan di tiga poin pertama.

  1. Periksa skema dalam kamus proxies — hampir selalu harus http://, bahkan untuk permintaan HTTPS.
  2. Uji proxy secara langsung melalui curl -x, untuk mengecualikan masalah di sisi kode.
  3. Pastikan login dan password tidak mengandung karakter khusus yang tidak di-escape dalam URL.
  4. Periksa apakah proxy terikat pada IP tertentu (whitelist) alih-alih otorisasi berdasarkan login/password.
  5. Tingkatkan timeout menjadi 15-30 detik sebelum menganggap proxy tidak berfungsi.
  6. Jika kesalahan muncul hanya di situs tertentu — masalah ada pada reputasi IP, bukan pada kode.
  7. Tambahkan logika retry dengan penundaan eksponensial alih-alih mencoba sekali.
  8. Dalam parsing massal, gunakan rotasi IP, bukan satu proxy statis untuk semua permintaan.

Kesimpulan

Sebagian besar kesalahan proxy dalam Python requests berkaitan dengan tiga hal: skema yang salah dalam URL proxy (http alih-alih https), tidak adanya atau format otorisasi yang salah, dan kualitas pool IP itu sendiri. ProxyError biasanya menunjukkan masalah koneksi atau pemblokiran IP, SSLError WRONG_VERSION_NUMBER hampir selalu menunjukkan skema proxy yang salah, dan 407 — menunjukkan masalah dengan login/password atau whitelist.

Jika Anda sering menghadapi pemblokiran dan kesalahan 407 saat melakukan parsing marketplace atau media sosial, sebaiknya tinjau sumber proxy itu sendiri, bukan hanya kode. Untuk parsing yang stabil dengan persentase pemblokiran yang rendah, kami merekomendasikan untuk mencoba proxy residensial — mereka menggunakan alamat IP nyata dan jauh lebih jarang menyebabkan ProxyError di situs yang dilindungi. Namun, jika kecepatan dan volume permintaan yang menjadi prioritas, bukan menghindari sistem anti-bot yang rumit, pertimbangkan untuk menggunakan proxy pusat data — mereka lebih murah dan lebih cepat untuk tugas parsing yang sederhana.