PHP cURL and Guzzle with AeonProxy proxies
A few cURL options, or one Guzzle setting, send PHP requests through residential or mobile IPs, rotating or sticky, over HTTP or SOCKS5.
- Protocols
- HTTP proxy for HTTP and HTTPS sites; SOCKS5 with
CURLPROXY_SOCKS5_HOSTNAMEorsocks5h:// - Authentication
CURLOPT_PROXYUSERPWD, or the login in Guzzle's proxy URL- Rotation
- A new IP per connection (a cURL handle or Guzzle client reuses its own); a
-sid-key keeps one IP for up to 60 minutes - Works with
- Residential and mobile proxies
Before you start
- PHP 8 with the curl extension (
php -mlistscurl). For Guzzle:composer require guzzlehttp/guzzle. - 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.
cURL
CURLOPT_PROXY takes the host and port, CURLOPT_PROXYUSERPWD the login and password. Leave CURLOPT_PROXYTYPE at CURLPROXY_HTTP for port 7000: cURL tunnels HTTPS sites through it with CONNECT. CURLPROXY_HTTPS or an https:// proxy URL would start TLS with the proxy itself, which fails.
<?php
$ch = curl_init("https://api.ipify.org");
curl_setopt_array($ch, [
CURLOPT_PROXY => "gate.aeonproxy.com:7000",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_PROXYUSERPWD => "LOGIN-cc-us:PASSWORD",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
if ($body === false) {
echo "cURL error: ", curl_error($ch), "\n";
} else {
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), " ", $body, "\n";
}When a request fails, curl_getinfo($ch, CURLINFO_HTTP_CONNECTCODE) returns the gateway's answer to the tunnel request (407, 402 and so on), while CURLINFO_RESPONSE_CODE stays 0.
Rotating or sticky
A rotating login gets a new IP for every connection. Each new cURL handle opens a new connection; reusing one handle keeps its connection, and its IP. A -sid- key keeps one IP across handles and scripts until its -ttl- runs out (1 to 60 minutes).
<?php
function ip(string $login): string
{
$ch = curl_init("https://api.ipify.org"); // a new handle opens a new connection
curl_setopt_array($ch, [
CURLOPT_PROXY => "gate.aeonproxy.com:7000",
CURLOPT_PROXYUSERPWD => "{$login}:PASSWORD",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
return curl_exec($ch) ?: curl_error($ch);
}
echo ip("LOGIN-cc-us"), " ", ip("LOGIN-cc-us"), "\n"; // two IPs
$sid = bin2hex(random_bytes(4)); // one key per session you want to keep
$login = "LOGIN-cc-us-sid-{$sid}-ttl-30";
echo ip($login), " ", ip($login), "\n"; // one IP for up to 30 minutesSOCKS5
Use port 7001 with CURLPROXY_SOCKS5_HOSTNAME, so the proxy resolves the site's name. Plain CURLPROXY_SOCKS5 resolves it on your server first, and that DNS lookup leaves from your own network.
<?php
$ch = curl_init("https://api.ipify.org");
curl_setopt_array($ch, [
CURLOPT_PROXY => "gate.aeonproxy.com:7001",
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
CURLOPT_PROXYUSERPWD => "LOGIN-cc-de:PASSWORD",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
echo curl_exec($ch) ?: curl_error($ch), "\n";Guzzle
Guzzle takes the whole proxy URL, login included, in its proxy option. A socks5h:// URL on port 7001 works the same way.
<?php
require "vendor/autoload.php";
use GuzzleHttp\Client;
$client = new Client([
"proxy" => "http://LOGIN-cc-us:[email protected]:7000",
// SOCKS5: "socks5h://LOGIN-cc-us:[email protected]:7001"
"timeout" => 30,
]);
echo $client->get("https://api.ipify.org")->getBody(), "\n";A Guzzle client keeps its connection between requests, so a rotating login keeps one IP. For a new IP on every request, add 'curl' => [CURLOPT_FORBID_REUSE => true] to the client options.
If it does not work
| What you see | What to check |
|---|---|
CONNECT tunnel failed, response 407 (cURL error 56, also in Guzzle) | The login, the password, or a key in the login that is not in the lists (a misspelled city, for example). |
The same with response 402 | No traffic left on the product, or the sub-user reached its limit. |
The same with response 502 | The exit failed. Retry: the gateway closes the connection after an error, so a rotating login gets a new IP on the next one. |
The same with response 403 | The site is blocked by default for every account: mail ports, .gov and .mil sites, some banking and ticketing sites. See gateway errors. |
SSL routines::wrong version number, or a hang | The proxy type is HTTPS. Use CURLPROXY_HTTP and an http:// proxy URL for port 7000. |
User was rejected by the SOCKS5 server (cURL error 97) | The gateway refused the SOCKS5 login. SOCKS5 has one failure code for every cause: check the login, the password, the keys and the traffic left. |
Questions
Yes, with curl_multi_* or Guzzle's concurrent requests. Bought traffic has no thread or connection limit on the gateway. Give each parallel job its own -sid- key if it needs its own sticky IP.
No. The country, region, city and session are keys in the login (LOGIN-cc-us-sid-abc123), so one login and password cover every location.