Kort antwoord
Hoe gebruik ik een roterende proxy in Node.js?
Gebruik fetch, maak een undici ProxyAgent voor http://gw.crawlrelay.com:7777 en geef dat door als dispatcher. Bij axios of got geef je een proxy-agent zoals https-proxy-agent of hpagent mee, en stel je proxy: false in bij axios. CrawlRelay mobiele 4G-proxy's lezen het land en sessie van de gebruikersnaam, van US$ 0,50/GB. Betaald in crypto, zonder KYC.
Node.js setup in een oogopslag
| fetch / undici | new ProxyAgent({ uri, token }), dan fetch(url, { dispatcher }) |
|---|---|
| axios | httpsAgent: new HttpsProxyAgent(url) en proxy: false |
| got | agent: { https: new HttpsProxyAgent({ proxy }) } van hpagent |
| SOCKS5 | socks-proxy-agent met een socks5h:// URL op poort 7778 |
| Nieuw IP per verzoek | Een nieuwe agent of een nieuwe sessie-ID per verzoek; gepoolde connecties behouden hun exit |
| Moduleformaat | Voorbeelden zijn ES-modules (.mjs of "type": "module") met top-level await |
Hoe gebruik ik een proxy met Node's fetch?
De globale fetch van Node is gebouwd op undici maar leest standaard geen HTTP_PROXY of HTTPS_PROXY. Installeer undici en geef een ProxyAgent mee als dispatcher. Het veld token verstuurt de inloggegevens als een Proxy-Authorization header, zodat er nooit een wachtwoord in een URL verschijnt die gelogd kan worden.
import { ProxyAgent, fetch } from "undici";
const credentials = Buffer.from("USERNAME-country-us:PASSWORD").toString("base64");
const dispatcher = new ProxyAgent({
uri: "http://gw.crawlrelay.com:7777",
token: `Basic ${credentials}`,
});
const res = await fetch("https://api.ipify.org?format=json", {
dispatcher,
signal: AbortSignal.timeout(30000),
});
console.log(res.status, await res.json());
await dispatcher.close();Hoe gebruik ik een proxy met axios?
Vertrouw niet op axios’s eigen proxy optie voor HTTPS-sites: deze stuurt het verzoek naar de proxy zonder CONNECT-tunnel, wat veel proxies weigeren. Schakel het uit met proxy: false en geef een agent mee die een juiste tunnel opent.
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const agent = new HttpsProxyAgent("http://USERNAME-country-de:[email protected]:7777");
const client = axios.create({ httpsAgent: agent, httpAgent: agent, proxy: false, timeout: 30000 });
const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data.ip);Hoe gebruik ik een proxy met got?
got gebruikt één agent per protocol. hpagent volgt Node’s http.Agent: keep-alive is uit tenzij je keepAlive: true meegeeft. Laat het uit of zet keepAlive: false zoals hieronder wanneer je elk verzoek op een nieuwe verbinding wilt, en dus meestal via een nieuwe exit.
import got from "got";
import { HttpsProxyAgent } from "hpagent";
const proxy = "http://USERNAME-country-fr:[email protected]:7777";
const body = await got("https://api.ipify.org", {
agent: { https: new HttpsProxyAgent({ proxy, keepAlive: false }) },
timeout: { request: 30000 },
retry: { limit: 2, statusCodes: [429, 502, 503, 504] },
}).text();
console.log(body);Hoe gebruik ik SOCKS5 in Node.js?
Gebruik socks-proxy-agent met het socks5h:// schema zodat de hostnaam bij de exit wordt opgelost. Het werkt met Node’s http en https modules en met elke bibliotheek die een agent accepteert.
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://USERNAME-country-gb:[email protected]:7778");
const req = https.get("https://api.ipify.org", { agent, timeout: 30000 }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => console.log(res.statusCode, body));
});
req.on("timeout", () => req.destroy(new Error("timeout after 30 s")));
req.on("error", (err) => console.error(err.code, err.message));Hoe beperk ik gelijktijdigheid per host zonder bibliotheek?
Promise.all over 10.000 URL’s opent 10.000 verzoeken tegelijk. Een kleine limiter per hostnaam houdt elk siteverzoek op een netjes niveau terwijl de crawl geheel parallel loopt. De onderstaande versie heeft geen afhankelijkheden en werkt met elke client hierboven.
import { ProxyAgent, fetch } from "undici";
const PER_HOST = 4;
const active = new Map();
const waiting = new Map();
const dispatcher = new ProxyAgent("http://USERNAME-country-us:[email protected]:7777");
async function withHostSlot(url, task) {
const host = new URL(url).hostname;
while ((active.get(host) ?? 0) >= PER_HOST) {
await new Promise((resolve) => {
if (!waiting.has(host)) waiting.set(host, []);
waiting.get(host).push(resolve);
});
}
active.set(host, (active.get(host) ?? 0) + 1);
try {
return await task();
} finally {
active.set(host, active.get(host) - 1);
waiting.get(host)?.shift()?.();
}
}
const urls = ["https://example.com/", "https://example.org/", "https://example.net/"];
const results = await Promise.all(
urls.map((url) =>
withHostSlot(url, async () => {
const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(30000) });
return [url, res.status, (await res.arrayBuffer()).byteLength];
}).catch((err) => [url, err.name, 0])
)
);
console.table(results);
await dispatcher.close();Waarom krijg ik twee keer hetzelfde IP of ECONNRESET?
Agents poolen connecties, en een gepoolde verbinding behoudt de exit waarmee hij geopend is. Voor een nieuw IP bij elk verzoek maak je een nieuwe agent per verzoek en sluit je die daarna, zet je keep-alive uit in de agent, of zet je een unieke -session-<id> in elke gebruikersnaam van het verzoek.
ECONNRESET en socket hang up komen meestal door het hergebruiken van een gepoolde socket die de andere kant al gesloten heeft, of door een exit die is weggevallen. Probeer GET-verzoeken één keer opnieuw op een nieuwe verbinding. De connection reset pagina behandelt de details.
Node.js en proxies: vragen
Ondersteunt Node.js fetch HTTP_PROXY?
Niet standaard in de versies die de meeste projecten nu gebruiken: de globale fetch negeert proxy-omgeving variabelen tenzij je een dispatcher meegeeft. Gebruik een undici ProxyAgent zoals hierboven getoond, of stel een globale dispatcher in met undici’s setGlobalDispatcher() als elk verzoek in het proces via de proxy moet verlopen.
Waarom faalt axios bij HTTPS-sites achter een proxy?
De ingebouwde proxy optie van axios stuurt HTTPS-verzoeken naar de proxy in een vorm die veel proxies weigeren, in plaats van een CONNECT-tunnel te openen. Zet proxy: false en geef een HttpsProxyAgent als httpsAgent mee. Het verzoek gaat dan door een juiste tunnel en TLS blijft tussen jouw code en de site.
Hoe verstuur ik verschillende landen vanuit één Node.js proces?
Maak per land een agent aan, elk met een eigen gebruikersnaam zoals USERNAME-country-de of USERNAME-country-jp, en kies per verzoek de juiste agent. Agents zijn goedkoop, en door ze apart te houden houd je ook hun connectiepools, en dus hun exits, gescheiden.
Welke timeout moet ik instellen in Node.js?
Stel er altijd één in: AbortSignal.timeout(30000) voor fetch, timeout: 30000 voor axios, timeout: { request: 30000 } voor got. Dertig seconden is geschikt voor HTML-pagina’s; geef trage doelen en mobiele exits tot 60 seconden, en probeer één keer opnieuw op een nieuwe verbinding in plaats van langer te wachten.
Verbind je Node.js crawler
US$ 5,94 voor 10 GB, US$ 0,50/GB van 50 GB.