Node.js with AeonProxy proxies
Send fetch and axios requests through residential or mobile IPs: one proxy URL with your login, rotating or sticky, over HTTP or SOCKS5.
- Protocols
- HTTP proxy for HTTP and HTTPS sites; SOCKS5 with
socks-proxy-agent - Authentication
- Login and password in the proxy URL
- Rotation
- A new IP per connection (an agent reuses its connection); a
-sid-key keeps one IP for up to 60 minutes - Works with
- Residential and mobile proxies
Before you start
npm install undicifor fetch, ornpm install axios https-proxy-agent socks-proxy-agentfor axios. The examples use the current versions; the current undici needs Node.js 22.19 or newer.- Your proxy login and password from the Residential or Mobile page of the dashboard, and traffic on that product (a login without traffic gets 402).
- Host
gate.aeonproxy.com- Port (HTTP / HTTPS)
7000- Port (SOCKS5)
7001- Login
- your proxy login, with targeting keys if you need them:
LOGIN-cc-us-sid-abc123 - Password
- your proxy password
Copy the login and password from the Residential or Mobile page of the dashboard; the generator there also writes ready lines. Key syntax: targeting and sessions.
fetch with undici's ProxyAgent
Put the login and password into the proxy URL. The scheme stays http:// for HTTPS sites too: the agent opens a CONNECT tunnel, and TLS runs between your code and the site.
import { fetch, ProxyAgent } from "undici";
const dispatcher = new ProxyAgent("http://LOGIN-cc-us:[email protected]:7000");
const res = await fetch("https://api.ipify.org", { dispatcher });
console.log(await res.text());Import fetch from undici as well. Node's built-in fetch runs the undici bundled with Node, and on Node 22 it rejects a ProxyAgent from the npm package with invalid onRequestStart method.
Rotating or sticky
A rotating login gets a new exit IP for every connection, not for every request. An agent keeps its connection open and reuses it, so requests through one agent share an IP, parallel ones included. For a new IP each time, open a new agent per request and close it afterwards. To keep one IP across agents and processes, add a -sid- key.
import { fetch, ProxyAgent } from "undici";
import { randomBytes } from "node:crypto";
async function exitIp(login) {
const dispatcher = new ProxyAgent(`http://${login}:[email protected]:7000`);
try {
const res = await fetch("https://api.ipify.org", { dispatcher });
return await res.text();
} finally {
await dispatcher.close(); // the next agent opens a new connection
}
}
// rotating: a new connection, a new IP
console.log(await exitIp("LOGIN-cc-us"), await exitIp("LOGIN-cc-us"));
// sticky: the same key keeps one IP for up to 30 minutes
const sticky = `LOGIN-cc-us-sid-${randomBytes(4).toString("hex")}-ttl-30`;
console.log(await exitIp(sticky), await exitIp(sticky));-ttl- sets how long the sticky IP is kept: 1 to 60 minutes, 10 when left out. Each line from the dashboard's generator carries its own key, so each line is its own sticky session.
axios
Pass an HttpsProxyAgent as httpAgent and httpsAgent, and set proxy: false so axios does not apply its own proxy handling or the HTTPS_PROXY variable on top. This agent opens a new connection for every request, so a rotating login changes IP on every call.
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const agent = new HttpsProxyAgent("http://LOGIN-cc-de:[email protected]:7000");
const api = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 30000 });
const r = await api.get("https://api.ipify.org");
console.log(r.data);axios also has a proxy option of its own. Versions before 1.16.1 send HTTPS requests through it as plain, unencrypted requests to the proxy, and those cannot reach an HTTPS site through the gateway; newer versions open a CONNECT tunnel. The agent works with every version.
SOCKS5
socks-proxy-agent connects to port 7001. With socks5h:// the proxy resolves host names, so DNS lookups do not leave from your own network; socks5:// resolves them on your machine first.
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://LOGIN-cc-de:[email protected]:7001");
const r = await axios.get("https://api.ipify.org", { httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 30000 });
console.log(r.data);undici's ProxyAgent also takes a socks5:// URL; Node prints a warning that this support is experimental. Since Node 22.21, the built-in fetch can also follow the HTTPS_PROXY variable when Node is started with NODE_USE_ENV_PROXY=1.
If it does not work
| What you see | What to check |
|---|---|
fetch failed, cause invalid onRequestStart method | Node's built-in fetch with a ProxyAgent from npm. Import fetch from undici too. |
Proxy response (407) !== 200 (undici) or status code 407 (axios) | The login, the password, or a key in the login that is not in the lists (a misspelled city, for example). |
| The same with 402 | No traffic left on the product, or the sub-user reached its limit. |
| The same with 502 | The exit failed. Retry: the next connection of a rotating login gets a new IP. |
Socks5 Authentication failed | The gateway refused the SOCKS5 login. SOCKS5 has one failure code for every cause, so check the login, the password, the keys and the traffic left. |
status code 400 and a page saying "The plain HTTP request was sent to HTTPS port" | axios before 1.16.1 with its own proxy option. Update axios or use HttpsProxyAgent as above. |
| The same IP on every request with a rotating login | One agent reuses its connection. Open a new agent per request, as above. |
Questions
Not with undici: one ProxyAgent can carry parallel requests over a single connection, so they share its IP. Give each worker its own agent, or its own -sid- key when the worker should keep its IP. Bought traffic has no thread or connection limit on the gateway.
Headless browsers take the proxy in their launch options, not through an agent. See the Puppeteer and Playwright pages.