Proxy Node.js: axios, fetch (undici), SOCKS5, dan sesi sticky
Cara pasang residential proxy di Node.js: fetch lewat undici ProxyAgent, axios dengan https-proxy-agent, SOCKS5, sesi sticky, retry, dan hemat kuota.
Mau pakai residential proxy dari skrip Node.js? Caranya beda per library. fetch bawaan Node secara default tidak memakai variabel HTTP_PROXY, sedangkan opsi proxy bawaan axios dikenal kurang andal untuk situs HTTPS. Panduan ini menunjukkan cara yang stabil untuk fetch (lewat undici), axios (lewat https-proxy-agent), dan SOCKS5, lengkap dengan sesi sticky, penanganan error, dan tips hemat kuota.
Yang perlu disiapkan
- Node.js versi 20 ke atas dan npm.
- Kuota GB yang aktif. Harganya mulai Rp 10.000 per GB tanpa langganan, dan saldo diisi lewat QRIS; rinciannya ada di halaman harga. Belum punya akun? Daftar di sini, tanpa email, cukup simpan token aksesnya.
- Username dan password proxy dari kartu Kredensial proxy di halaman Ringkasan dashboard. HTTP, HTTPS, dan SOCKS5 memakai endpoint yang sama:
proxy.waroengproxy.com:8000.
Install paket yang dipakai di panduan ini:
npm install undici axios https-proxy-agent socks-proxy-agent
Semua contoh memakai sintaks ES module dan await di level atas. Simpan file dengan ekstensi .mjs, atau tambahkan "type": "module" di package.json.
fetch dengan ProxyAgent dari undici
fetch di Node dibangun di atas undici. Supaya request lewat proxy, buat sebuah ProxyAgent lalu kirimkan lewat opsi dispatcher. Username dan password ditulis langsung di URL proxy, dan target lokasi ditempel di username, misalnya -cc-ID untuk IP Indonesia.
import { fetch, ProxyAgent } from 'undici';const proxy = new ProxyAgent('http://USERNAME-cc-ID:PASSWORD@proxy.waroengproxy.com:8000');const res = await fetch('https://ipinfo.io/json', {dispatcher: proxy,signal: AbortSignal.timeout(30_000),});console.log(res.status, await res.json());
Impor fetch dari paket undici yang sama dengan ProxyAgent. Mencampur fetch global milik Node dengan ProxyAgent dari versi undici yang berbeda kadang memicu error yang sulit dilacak.
Jalankan skripnya dua kali. Karena mode bawaannya rotating, IP di respons biasanya berganti. Perlu dicatat: satu ProxyAgent menjaga koneksi tetap terbuka (keep-alive), jadi beberapa request beruntun ke situs yang sama dalam satu proses bisa keluar dari IP yang sama. Kalau tiap alur kerja wajib punya IP sendiri, pakai sesi sticky dengan label berbeda seperti di bagian bawah.
axios dengan https-proxy-agent
Untuk axios, matikan opsi proxy bawaannya dengan proxy: false, lalu serahkan koneksi ke agent dari paket https-proxy-agent. Agent ini membuka terowongan ke situs tujuan lewat proxy, sehingga koneksi HTTPS tetap terenkripsi dari ujung ke ujung.
import axios from 'axios';import { HttpsProxyAgent } from 'https-proxy-agent';const agent = new HttpsProxyAgent('http://USERNAME-cc-ID:PASSWORD@proxy.waroengproxy.com:8000');const client = axios.create({httpsAgent: agent,proxy: false,timeout: 30_000,});const { data } = await client.get('https://ipinfo.io/json');console.log(data);
proxy: false itu penting. Tanpa opsi ini, axios bisa ikut membaca variabel HTTPS_PROXY dari sistem dan bentrok dengan agent. Agent di atas menangani situs https://. Kalau masih ada target http://, pasang juga httpAgent dari paket http-proxy-agent dengan URL proxy yang sama.
SOCKS5 dengan socks-proxy-agent
Endpoint dan kredensial SOCKS5 sama persis, cukup ganti skemanya. Pakai socks5h:// supaya nama domain di-resolve oleh proxy, bukan oleh DNS lokalmu. Dengan socks5:// biasa, DNS lokal bisa mengarahkanmu ke server CDN yang dekat dengan lokasimu, bukan lokasi IP proxy. Perbedaan kedua protokol ini dibahas di HTTP, HTTPS, atau SOCKS5?
import axios from 'axios';import { SocksProxyAgent } from 'socks-proxy-agent';const agent = new SocksProxyAgent('socks5h://USERNAME-cc-ID:PASSWORD@proxy.waroengproxy.com:8000');const { data } = await axios.get('https://ipinfo.io/json', {httpAgent: agent,httpsAgent: agent,proxy: false,timeout: 30_000,});console.log(data);
Sesi sticky: satu IP untuk satu alur kerja
Rotating cocok untuk request yang saling lepas, misalnya mengecek banyak halaman produk yang berbeda. Kalau beberapa request harus terlihat datang dari IP yang sama, misalnya membuka halaman pertama lalu paginasinya, tambahkan -s-<label> dan -ttl-<detik> di username. Label yang sama berarti IP yang sama selama TTL berlaku. TTL bisa diisi 1 sampai 86400 detik, dan bawaannya 60 detik. Kapan memilih yang mana dijelaskan di sticky atau rotating.
Pola yang rapi: setiap worker punya label sendiri, jadi beberapa alur berjalan paralel dari IP yang berbeda tanpa saling mengganggu.
import { fetch, ProxyAgent } from 'undici';import { randomBytes } from 'node:crypto';const HOST = 'proxy.waroengproxy.com:8000';const PASS = encodeURIComponent('PASSWORD');// Label acak heksadesimal, tanpa tanda minusfunction stickyAgent(ttl = 600) {const sid = randomBytes(5).toString('hex');return new ProxyAgent(`http://USERNAME-cc-ID-s-${sid}-ttl-${ttl}:${PASS}@${HOST}`);}const urls = ['https://example.com/a', 'https://example.com/b', 'https://example.com/c'];async function worker() {const dispatcher = stickyAgent();while (urls.length) {const url = urls.shift();const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(30_000) });console.log(res.status, url);await new Promise((r) => setTimeout(r, 1000)); // jeda sopan antar-request}await dispatcher.close();}await Promise.all([worker(), worker()]);
Label sesi tidak boleh mengandung tanda minus, karena minus adalah pemisah antarparameter di username. Kalau password-mu memuat karakter seperti @, :, atau /, bungkus dengan encodeURIComponent seperti di contoh supaya URL proxy tidak rusak.
Menangani error dan timeout
- 407 Proxy Authentication Required: username atau password salah, atau ada parameter target yang tidak valid. Satu nilai yang keliru membuat seluruh username ditolak. Untuk situs HTTPS, undici biasanya melempar error yang menyebut kode 407, bukan mengembalikannya di
res.status. Retry tidak membantu di sini; perbaiki kredensialnya dulu. - Koneksi ditolak saat memakai filter lokasi: tidak ada IP yang cocok dengan semua filter sekaligus, misalnya kota dan ISP bersamaan. Longgarkan ke tingkat negara.
- Timeout atau koneksi terputus: selalu pasang batas waktu, lalu coba ulang dengan sesi baru beberapa kali saja. Jangan retry tanpa batas, karena setiap percobaan tetap memakai kuota.
- 403 atau 429 dari situs tujuan: itu keputusan situsnya, bukan proxy. Turunkan kecepatan, kurangi request paralel, dan patuhi ToS serta robots.txt situs tersebut.
Contoh retry sederhana yang membedakan kesalahan kredensial dari gangguan jaringan:
async function fetchWithRetry(url, tries = 3) {for (let i = 1; i <= tries; i++) {const dispatcher = stickyAgent(); // IP baru di setiap percobaantry {const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(30_000) });if (res.status < 500 || i === tries) return res;} catch (err) {// fetch membungkus error asli di err.causeif (String(err.cause ?? err).includes('407')) throw err; // kredensial salahif (i === tries) throw err;}await new Promise((r) => setTimeout(r, 2000 * i));}}
Daftar penyebab yang lebih lengkap ada di panduan mengatasi error proxy.
Hemat kuota dari Node.js
Karena tagihannya per GB, setiap byte yang lewat proxy ikut dihitung. Beberapa kebiasaan kecil yang berdampak besar:
- Pakai ulang satu agent untuk banyak request, jangan membuat agent baru di setiap request. Koneksi keep-alive mengurangi handshake TLS yang berulang.
- Ambil hanya yang kamu perlukan. Kalau situs menyediakan API atau feed publik resmi, ukurannya biasanya jauh lebih kecil daripada halaman HTML penuh.
- Biarkan kompresi tetap aktif. fetch dan axios di Node sudah meminta respons terkompresi dan membukanya otomatis.
- Pakai metode
HEADkalau kamu cuma butuh status atau header. - Kalau memakai headless browser, blokir gambar dan font; caranya ada di panduan Playwright dan Puppeteer.
Untuk memperkirakan kebutuhan GB dengan lebih teliti, baca berapa GB yang sebenarnya kamu butuhkan.
PROXY_URL, lalu baca dengan process.env.PROXY_URL. Kalau kredensial terlanjur bocor, klik Ganti password di Ringkasan dan perbarui semua skrip yang memakainya.Langkah berikutnya
Ringkasnya: fetch memakai ProxyAgent dari undici, axios memakai HttpsProxyAgent dengan proxy: false, dan SOCKS5 memakai SocksProxyAgent dengan skema socks5h://. Semuanya mengarah ke endpoint yang sama. Untuk membuat banyak baris proxy dengan target negara atau sesi sticky tanpa merakit username manual, pakai Generator proxy. Referensi semua parameter username ada di dokumentasi, dan kalau kamu juga menulis Python, panduannya ada di proxy Python requests.
Belum punya akun? Buat akun, isi saldo lewat QRIS, lalu jalankan contoh fetch pertama di atas. Prosesnya cuma beberapa menit.