Voltar ao blog

Configuração de Proxy em PHP com cURL e Guzzle HTTP Client: guia completo com exemplos de código

Guia completo para configurar proxy em PHP usando cURL e Guzzle HTTP Client — com exemplos de código, rotação de IP e dicas para escolher o tipo de proxy para scraping e automação.

📅12 de agosto de 2026
```html

Se você está escrevendo um parser, automatizando a coleta de dados ou contornando restrições de IP — não há como evitar o uso de proxy em PHP. Neste guia, vamos explorar duas ferramentas principais: a extensão embutida cURL e a popular biblioteca Guzzle HTTP Client — com exemplos de código prontos para serem usados em seu projeto.

Por que usar proxy em projetos PHP

PHP continua sendo uma das linguagens mais populares para automação no servidor, e tarefas que exigem proxy são comuns. Aqui estão os principais cenários onde o uso de proxy é essencial:

  • Scraping de sites e marketplaces — Wildberries, Ozon, Avito, AliExpress bloqueiam IPs após algumas dezenas de requisições. Proxies permitem distribuir a carga entre diferentes endereços e evitar 403/429.
  • Coleta de dados de recursos geodependentes — preços, resultados de buscadores, conteúdo podem variar dependendo do país. Proxies com a geolocalização necessária resolvem esse problema.
  • Contornar rate limiting — muitas APIs limitam o número de requisições de um único IP. A rotação de proxies permite contornar esses limites.
  • Teste de conteúdo geodependente — verificar como o site aparece para usuários de diferentes países, sem sair do escritório.
  • Anonimato na automação — ocultar o IP real do servidor ao fazer requisições em massa a recursos externos.
  • Monitoramento de concorrentes — coleta regular de preços, sortimentos, promoções de sites concorrentes sem risco de ser banido.

Em PHP, para requisições HTTP, normalmente usamos duas ferramentas: a extensão embutida cURL e a biblioteca Guzzle HTTP Client. Ambas suportam proxies HTTP, HTTPS, SOCKS4 e SOCKS5 — vamos analisar cada uma em detalhes.

Qual tipo de proxy escolher para PHP

Antes de escrever o código, é importante entender qual tipo de proxy é adequado para sua tarefa. Diferentes tipos têm características distintas em termos de velocidade, confiabilidade e grau de anonimato.

Tipo de Proxy Velocidade Anonimato Melhor para
Proxies de Data Center Muito alta Média Scraping sem sistemas de anti-bot rigorosos, requisições de API
Proxies Residenciais Média Alta Scraping de sites protegidos, marketplaces, dados geográficos
Proxies Móveis Média Máxima Sites com proteção anti-bot rigorosa, redes sociais

Para a maioria das tarefas de scraping de dados em marketplaces como Wildberries ou Ozon, a escolha ideal são os proxies residenciais — seus IPs pertencem a usuários reais, tornando as requisições praticamente indistinguíveis do tráfego normal de navegador. Proxies de data center são adequados onde a velocidade é mais importante que a invisibilidade, e a proteção é fraca.

Todos os três tipos de proxy suportam os protocolos HTTP/HTTPS e SOCKS5, portanto, em termos de código — a configuração é a mesma. A única diferença está na string de conexão.

Proxy em cURL: configuração básica

A extensão cURL está disponível no PHP por padrão e é a maneira padrão de executar requisições HTTP no servidor. Para conectar um proxy, usamos duas opções principais: CURLOPT_PROXY e CURLOPT_PROXYTYPE.

Proxy HTTP sem autenticação

<?php

$ch = curl_init();

curl_setopt_array($ch, [
    CURLOPT_URL            => 'https://httpbin.org/ip',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 30,

    // Especificamos o endereço do proxy
    CURLOPT_PROXY          => '185.199.100.1:8080',

    // Tipo de proxy: HTTP (por padrão)
    CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "Código HTTP: $httpCode\n";
echo $response;

Aqui CURLOPT_PROXY aceita uma string no formato host:port. Para tráfego HTTPS através de um proxy HTTP, o cURL usa automaticamente o método CONNECT — tunelamento, portanto, o conteúdo da requisição permanece criptografado.

Opções úteis do cURL para trabalhar com proxies

Opção Descrição
CURLOPT_PROXY Endereço do servidor proxy (host:port)
CURLOPT_PROXYTYPE Tipo: CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5
CURLOPT_PROXYUSERPWD Login e senha no formato user:password
CURLOPT_HTTPPROXYTUNNEL Ativar tunelamento através do HTTP CONNECT
CURLOPT_SSL_VERIFYPEER Verificação do certificado SSL (false — desativar)
CURLOPT_TIMEOUT Timeout da requisição em segundos
CURLOPT_CONNECTTIMEOUT Timeout de conexão ao proxy

Autenticação e SOCKS5 em cURL

A maioria dos proxies comerciais requer autenticação por login e senha. Além disso, SOCKS5 é o protocolo preferido quando é necessária total anonimidade, pois não adiciona cabeçalhos como X-Forwarded-For, que podem revelar o uso de proxy.

Proxy HTTP com login e senha

<?php

$proxyHost = '185.199.100.1';
$proxyPort = '8080';
$proxyUser = 'your_login';
$proxyPass = 'your_password';

$ch = curl_init();

curl_setopt_array($ch, [
    CURLOPT_URL            => 'https://httpbin.org/ip',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_CONNECTTIMEOUT => 10,

    // Proxy com autenticação
    CURLOPT_PROXY          => "$proxyHost:$proxyPort",
    CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,
    CURLOPT_PROXYUSERPWD   => "$proxyUser:$proxyPass",

    // Tunelamento para HTTPS
    CURLOPT_HTTPPROXYTUNNEL => true,

    // Cabeçalhos do navegador para disfarce
    CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    CURLOPT_HTTPHEADER     => [
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language: ru-RU,ru;q=0.9,en;q=0.8',
    ],
]);

$response = curl_exec($ch);

if (curl_errno($ch)) {
    echo 'Erro cURL: ' . curl_error($ch);
} else {
    echo $response;
}

curl_close($ch);

Proxy SOCKS5 em cURL

<?php

$ch = curl_init();

curl_setopt_array($ch, [
    CURLOPT_URL            => 'https://httpbin.org/ip',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,

    CURLOPT_PROXY          => '185.199.100.1:1080',

    // SOCKS5 com resolução de DNS através do proxy (recomendado!)
    CURLOPT_PROXYTYPE      => CURLPROXY_SOCKS5_HOSTNAME,

    // Autenticação (se necessário)
    CURLOPT_PROXYUSERPWD   => 'login:password',
]);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

💡 Importante: SOCKS5 vs SOCKS5_HOSTNAME

Use CURLPROXY_SOCKS5_HOSTNAME em vez de CURLPROXY_SOCKS5. A diferença é que com SOCKS5_HOSTNAME as requisições DNS também passam pelo proxy, o que evita vazamentos de DNS e aumenta a anonimidade. Com SOCKS5 normal, o DNS é resolvido localmente — isso pode revelar seu IP real.

Rotação de proxy em cURL

Um único proxy rapidamente será bloqueado ao fazer requisições em massa. A estratégia correta é ter um pool de proxies e alterná-los. Aqui está uma implementação simples, mas funcional:

<?php

class ProxyRotator
{
    private array $proxies;
    private int $currentIndex = 0;

    public function __construct(array $proxies)
    {
        $this->proxies = $proxies;
        shuffle($this->proxies); // Embaralha para ordem aleatória
    }

    /**
     * Obter o próximo proxy do pool
     */
    public function getNext(): string
    {
        $proxy = $this->proxies[$this->currentIndex];
        $this->currentIndex = ($this->currentIndex + 1) % count($this->proxies);
        return $proxy;
    }

    /**
     * Obter um proxy aleatório
     */
    public function getRandom(): string
    {
        return $this->proxies[array_rand($this->proxies)];
    }
}

// Lista de proxies no formato login:password@host:port
$proxyList = [
    'user1:[email protected]:8080',
    'user2:[email protected]:8080',
    'user3:[email protected]:8080',
    'user4:[email protected]:8080',
];

$rotator = new ProxyRotator($proxyList);

/**
 * Função de requisição com seleção automática de proxy
 */
function fetchWithProxy(string $url, ProxyRotator $rotator): ?string
{
    $proxyStr = $rotator->getNext();

    // Faz o parsing da string do proxy
    preg_match('/^(.+):(.+)@(.+):(\d+)$/', $proxyStr, $m);
    [, $user, $pass, $host, $port] = $m;

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 20,
        CURLOPT_CONNECTTIMEOUT => 8,
        CURLOPT_PROXY          => "$host:$port",
        CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,
        CURLOPT_PROXYUSERPWD   => "$user:$pass",
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
        CURLOPT_SSL_VERIFYPEER => false,
    ]);

    $response = curl_exec($ch);
    $error    = curl_error($ch);
    curl_close($ch);

    if ($error) {
        error_log("Proxy $host:$port indisponível: $error");
        return null;
    }

    return $response;
}

// Exemplo: scraping de 10 páginas com rotação de proxies
$urls = [
    'https://example.com/page/1',
    'https://example.com/page/2',
    'https://example.com/page/3',
    // ...
];

foreach ($urls as $url) {
    $html = fetchWithProxy($url, $rotator);
    if ($html) {
        echo "Recebido: " . strlen($html) . " bytes\n";
    }
    usleep(500000); // Pausa de 0.5 seg entre requisições
}

Note a usleep(500000) — a pausa entre requisições é criticamente importante. Mesmo com rotação de proxies, requisições muito frequentes podem levar ao bloqueio por padrões de comportamento. O intervalo recomendado é de 500 ms a 2 segundos, dependendo do site.

Proxy em Guzzle HTTP Client: configuração básica

Guzzle é uma poderosa biblioteca PHP para requisições HTTP, que é usada na maioria dos modernos frameworks PHP (Laravel, Symfony). Ela oferece uma API mais conveniente e legível em comparação com o cURL puro, suporta requisições assíncronas, middleware e um tratamento de erros conveniente.

Instalação via Composer

composer require guzzlehttp/guzzle

Proxy HTTP sem autenticação

<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client([
    // URL base (opcional)
    'base_uri' => 'https://httpbin.org',

    // Configurações padrão para todas as requisições
    'timeout'  => 30,
    'connect_timeout' => 10,

    // Proxy para todas as requisições do cliente
    'proxy' => 'http://185.199.100.1:8080',
]);

$response = $client->get('/ip');

echo $response->getStatusCode() . "\n";  // 200
echo $response->getBody() . "\n";        // {"origin": "185.199.100.1"}

No Guzzle, o proxy é definido através da opção proxy no formato URL. Isso é mais intuitivo do que no cURL. O proxy pode ser definido tanto no nível do cliente (para todas as requisições) quanto para cada requisição individualmente.

Proxy HTTP com autenticação

<?php

use GuzzleHttp\Client;

$login    = 'your_login';
$password = 'your_password';
$host     = '185.199.100.1';
$port     = '8080';

$client = new Client([
    'timeout' => 30,
]);

// Proxy com autenticação é passado no formato URL
$response = $client->get('https://httpbin.org/ip', [
    'proxy' => "http://$login:$password@$host:$port",
    'headers' => [
        'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept'     => 'text/html,application/xhtml+xml,application/xml;q=0.9',
    ],
]);

echo $response->getBody();

O formato do URL do proxy no Guzzle é: scheme://user:password@host:port. Para proxies HTTP, usamos http://, para SOCKS5 — socks5://.

Trabalho avançado com Guzzle: timeouts, cabeçalhos, SOCKS5

Vamos considerar cenários mais complexos: diferentes proxies para HTTP e HTTPS, SOCKS5, desativação da verificação SSL e configuração de cabeçalhos para simular um navegador.

Diferentes proxies para HTTP e HTTPS

<?php

use GuzzleHttp\Client;

$client = new Client([
    'timeout' => 30,
    'proxy'   => [
        // Proxy para requisições HTTP
        'http'  => 'http://login:[email protected]:8080',
        // Proxy para requisições HTTPS
        'https' => 'http://login:[email protected]:8080',
        // Exceções — esses hosts vão sem proxy
        'no'    => ['localhost', '127.0.0.1', '.internal.corp'],
    ],
]);

SOCKS5 no Guzzle

<?php

use GuzzleHttp\Client;

// Para SOCKS5 no Guzzle, é necessário um pacote adicional
// composer require clue/socks-react (ou use o curl handler)

$client = new Client([
    'timeout' => 30,
    'proxy'   => 'socks5://login:[email protected]:1080',
    'curl'    => [
        CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
    ],
]);

$response = $client->get('https://httpbin.org/ip');
echo $response->getBody();

Configuração completa com cabeçalhos de navegador

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

$client = new Client([
    'timeout'         => 30,
    'connect_timeout' => 10,
    'verify'          => false, // Desativar verificação SSL (para depuração)
    'allow_redirects' => [
        'max'       => 5,
        'strict'    => false,
        'referer'   => true,
        'protocols' => ['http', 'https'],
    ],
    'headers' => [
        'User-Agent'      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language' => 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
        'Accept-Encoding' => 'gzip, deflate, br',
        'Cache-Control'   => 'no-cache',
        'Connection'      => 'keep-alive',
    ],
]);

$response = $client->get('https://example.com/catalog', [
    'proxy' => 'http://login:[email protected]:8080',
]);

$statusCode = $response->getStatusCode();
$body       = (string) $response->getBody();

echo "Status: $statusCode, Tamanho: " . strlen($body) . " bytes\n";

⚠️ Sobre verify => false

Desativar a verificação SSL ('verify' => false) é aceitável apenas para depuração ou quando se trabalha com serviços internos. No código de produção, sempre mantenha a verificação SSL ativada, caso contrário, você estará vulnerável a ataques do tipo man-in-the-middle.

Rotação de proxy em Guzzle

No Guzzle, a rotação pode ser convenientemente implementada através de middleware — uma camada intermediária que intercepta cada requisição e adiciona a ela um proxy. Isso é mais elegante do que passar o proxy manualmente em cada chamada.

<?php

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;

/**
 * Middleware para rotação automática de proxies
 */
function proxyRotationMiddleware(array $proxies): callable
{
    $index = 0;
    $total = count($proxies);

    return Middleware::mapRequest(
        function (RequestInterface $request) use ($proxies, &$index, $total) {
            $proxy = $proxies[$index % $total];
            $index++;

            // Adiciona o proxy nos atributos da requisição
            // (passa através das opções no handler)
            return $request->withHeader('X-Selected-Proxy', $proxy);
        }
    );
}

// Lista de proxies
$proxies = [
    'http://user1:[email protected]:8080',
    'http://user2:[email protected]:8080',
    'http://user3:[email protected]:8080',
];

// Variante simples: classe wrapper sobre Guzzle com rotação
class GuzzleWithRotation
{
    private Client $client;
    private array $proxies;
    private int $index = 0;

    public function __construct(array $proxies, array $clientConfig = [])
    {
        $this->proxies = $proxies;
        $this->client  = new Client($clientConfig);
    }

    public function get(string $url, array $options = []): \GuzzleHttp\Psr7\Response
    {
        $options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
        $this->index++;

        return $this->client->get($url, $options);
    }

    public function post(string $url, array $options = []): \GuzzleHttp\Psr7\Response
    {
        $options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
        $this->index++;

        return $this->client->post($url, $options);
    }
}

// Uso
$guzzle = new GuzzleWithRotation($proxies, [
    'timeout' => 30,
    'headers' => [
        'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
    ],
]);

$urls = [
    'https://example.com/product/1',
    'https://example.com/product/2',
    'https://example.com/product/3',
];

foreach ($urls as $url) {
    try {
        $response = $guzzle->get($url);
        echo "OK [{$response->getStatusCode()}]: $url\n";
        sleep(1);
    } catch (\Exception $e) {
        echo "Erro: " . $e->getMessage() . "\n";
    }
}

Tratamento de erros e depuração

Ao trabalhar com proxies, erros são inevitáveis: o proxy pode estar indisponível, responder lentamente, ou o site de destino pode retornar um erro. É importante tratar todas essas situações adequadamente.

Tratamento de erros em cURL

<?php

function fetchWithErrorHandling(string $url, string $proxy): array
{
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 20,
        CURLOPT_CONNECTTIMEOUT => 8,
        CURLOPT_PROXY          => $proxy,
        CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,
    ]);

    $body     = curl_exec($ch);
    $errno    = curl_errno($ch);
    $error    = curl_error($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
    curl_close($ch);

    // Códigos de erro cURL para proxies
    $proxyErrors = [
        CURLE_COULDNT_CONNECT    => 'Não foi possível conectar ao proxy',
        CURLE_OPERATION_TIMEDOUT => 'Timeout de conexão ao proxy',
        CURLE_RECV_ERROR         => 'Erro ao receber dados',
        CURLE_SSL_CONNECT_ERROR  => 'Erro SSL através do proxy',
    ];

    if ($errno) {
        $message = $proxyErrors[$errno] ?? "Erro cURL #$errno: $error";
        return ['success' => false, 'error' => $message, 'code' => $errno];
    }

    if ($httpCode >= 400) {
        return ['success' => false, 'error' => "HTTP $httpCode", 'code' => $httpCode];
    }

    return [
        'success' => true,
        'body'    => $body,
        'code'    => $httpCode,
        'time'    => round($totalTime, 3),
    ];
}

// Uso com tentativas repetidas
function fetchWithRetry(string $url, array $proxies, int $maxRetries = 3): ?string
{
    foreach ($proxies as $proxy) {
        for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
            $result = fetchWithErrorHandling($url, $proxy);

            if ($result['success']) {
                echo "Sucesso através de $proxy (tentativa $attempt, {$result['time']}s)\n";
                return $result['body'];
            }

            echo "Erro através de $proxy: {$result['error']}\n";

            if ($attempt < $maxRetries) {
                sleep(2); // Pausa antes de repetir
            }
        }
    }

    return null; // Todos os proxies falharam
}

Tratamento de erros em Guzzle

<?php

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\Exception\ClientException;

$client = new Client(['timeout' => 30]);

$proxies = [
    'http://user1:[email protected]:8080',
    'http://user2:[email protected]:8080',
];

function fetchGuzzleWithFallback(Client $client, string $url, array $proxies): ?string
{
    foreach ($proxies as $proxy) {
        try {
            $response = $client->get($url, [
                'proxy'   => $proxy,
                'timeout' => 20,
            ]);

            return (string) $response->getBody();

        } catch (ConnectException $e) {
            // Proxy indisponível ou timeout de conexão
            echo "Proxy indisponível ($proxy): " . $e->getMessage() . "\n";

        } catch (ClientException $e) {
            // HTTP 4xx — erro do cliente (403, 404, 429)
            $code = $e->getResponse()->getStatusCode();
            echo "HTTP $code para $url através de $proxy\n";

            if ($code === 429) {
                echo "Limite de taxa — pausa de 5 segundos\n";
                sleep(5);
            }

        } catch (ServerException $e) {
            // HTTP 5xx — erro do servidor
            echo "Erro do servidor: " . $e->getResponse()->getStatusCode() . "\n";

        } catch (RequestException $e) {
            // Outros erros de requisição
            echo "Erro de requisição: " . $e->getMessage() . "\n";
        }
    }

    return null;
}

cURL vs Guzzle: o que escolher

Ambas as ferramentas funcionam bem com proxies, mas têm diferentes pontos fortes. Aqui está uma comparação com base em critérios-chave:

Critério cURL Guzzle
Instalação ✅ Integrado ao PHP ⚠️ Necessita Composer
Legibilidade do código ⚠️ Muitas opções, prolixo ✅ API limpa e conveniente
Desempenho ✅ Um pouco mais rápido (sem wrappers) ✅ Comparável, tem async
Requisições assíncronas ⚠️ curl_multi (difícil) ✅ Suporte embutido
Middleware / hooks ❌ Não ✅ HandlerStack, Middleware
Suporte a SOCKS5 ✅ Nativo ✅ Através do curl handler
Tratamento de erros ⚠️ Códigos de erro manualmente ✅ Exceções com tipos
Integração em Laravel/Symfony ⚠️ Manualmente ✅ Suporte nativo
Adequado para Scripts simples, sem dependências Projetos em frameworks, lógica complexa

Recomendação: Se você está escrevendo um script simples ou trabalhando em um servidor sem Composer — use cURL. Para projetos em Laravel, Symfony ou qualquer aplicação PHP moderna — Guzzle será significativamente mais conveniente e oferecerá mais possibilidades de escalabilidade.

🚀 Checklist rápido antes de iniciar

  • ✅ Verifique se o proxy está funcionando: curl -x http://login:pass@host:port https://httpbin.org/ip
  • ✅ Defina timeouts: timeout e connect_timeout
  • ✅ Adicione um User-Agent realista
  • ✅ Implemente pausas entre requisições (mínimo 500 ms)
  • ✅ Preveja tratamento de erros e fallback para outro proxy
  • ✅ Para SOCKS5, use CURLPROXY_SOCKS5_HOSTNAME (não SOCKS5)
  • ✅ Não desative a verificação SSL em produção

Conclusão

Configurar proxy em PHP é uma tarefa simples, se você souber as opções e formatos corretos. Para tarefas básicas, basta usar cURL com CURLOPT_PROXY e CURLOPT_PROXYUSERPWD. Para projetos em frameworks, Guzzle oferece uma API mais conveniente, exceções tipadas e suporte a middleware para rotação de proxies.

Princípios-chave para um funcionamento confiável: use SOCKS5 com resolução de DNS através do proxy (CURLPROXY_SOCKS5_HOSTNAME), sempre defina timeouts, adicione pausas entre requisições e implemente rotação de proxies para tarefas em larga escala. O tratamento de erros com fallback para outro proxy é um elemento obrigatório em qualquer código de produção.

Se você seguir essas diretrizes, estará bem preparado para trabalhar com proxies em PHP de forma eficaz e segura.

```