Voltar ao blog

Proxies no GitHub Actions e pipelines CI/CD: guia completo com exemplos de código

Entendemos como conectar um proxy ao workflow do GitHub Actions - para que as tarefas automáticas não sejam bloqueadas e funcionem na região desejada.

📅20 de julho de 2026
```html

GitHub Actions é uma poderosa ferramenta de automação: ela executa testes, faz deploy de aplicativos, coleta dados e realiza dezenas de outras tarefas. Mas assim que o workflow começa a acessar recursos externos — marketplaces, plataformas de publicidade, APIs estrangeiras — ele imediatamente se depara com bloqueios geográficos e limites de IP. A solução é simples: conectar um proxy diretamente no pipeline.

Por que usar proxies no GitHub Actions: cenários reais

Muitas equipes usam GitHub Actions não apenas para fazer deploy de código, mas também para automatizar tarefas de negócios: monitoramento de preços de concorrentes, coleta de dados de marketplaces, verificação automática de contas de anúncios e testes de sites de diferentes regiões. Todas essas tarefas têm um problema em comum — o runner do GitHub Actions tem um IP fixo da faixa do Microsoft Azure, e muitos serviços o bloqueiam ou limitam.

Aqui estão situações específicas em que um proxy é indispensável:

  • Scraping de Wildberries, Ozon, Avito — essas plataformas já bloquearam faixas de IP de provedores de nuvem. Uma solicitação do runner do GitHub Actions será bloqueada ou receberá um captcha já na 2ª ou 3ª tentativa.
  • Testes geotargetizados — profissionais de marketing e engenheiros de QA verificam como o site ou o anúncio aparecem para usuários de Moscovo, Berlim ou Nova Iorque. Sem um proxy, o runner sempre "verá" o conteúdo de uma única região.
  • Trabalho com APIs limitadas por região — algumas APIs (por exemplo, versões regionais do Google Ads, Facebook Marketing API com configurações específicas) retornam dados diferentes dependendo da geolocalização da solicitação.
  • Monitoramento de concorrentes — a coleta automática de preços, promoções e sortimentos requer solicitações regulares, que são facilmente detectadas por um IP repetido de um data center.
  • Automação de verificações de anúncios — arbitradores e profissionais de marketing de performance executam verificações automáticas do status de anúncios, saldos e métricas através de scripts em CI/CD.
  • Testes de integração com serviços externos — alguns serviços bloqueiam solicitações de faixas do Azure por motivos de segurança, e os testes simplesmente falham sem explicações.

Em todos esses casos, o proxy resolve o problema de forma radical: o workflow começa a parecer uma solicitação de um usuário comum da cidade desejada, e não de um servidor em nuvem da Microsoft.

Como o GitHub Actions funciona com a rede

Antes de configurar um proxy, é importante entender a arquitetura da rede no GitHub Actions. Quando você executa um workflow em um runner padrão ubuntu-latest, a tarefa é executada em uma máquina virtual na infraestrutura do Microsoft Azure. Cada uma dessas máquinas tem um IP público da faixa do Azure — e é esse IP que os serviços externos veem.

Características-chave da rede no GitHub Actions:

  • O IP muda a cada execução — mas permanece dentro das faixas conhecidas do Azure, que são facilmente detectáveis.
  • Não há suporte embutido para proxies — o GitHub não fornece um mecanismo nativo para proxy de tráfego.
  • Variáveis de ambiente funcionam globalmente — se você definir HTTP_PROXY no nível do job, todos os passos dentro desse job usarão o proxy.
  • Runners auto-hospedados — uma alternativa em que você executa o runner em seu próprio servidor. Nesse caso, o proxy é configurado no nível do servidor, e não do workflow.

Para a maioria das tarefas, a abordagem ideal é configurar o proxy através de variáveis de ambiente diretamente no arquivo do workflow (.github/workflows/seu-workflow.yml). Este é um método universal que funciona para a maioria das ferramentas: curl, wget, Python requests, Node.js http, Go net/http e outras.

Qual tipo de proxy escolher para CI/CD

A escolha do tipo de proxy depende da tarefa. Para pipelines CI/CD, três opções são relevantes, e cada uma tem seu nicho:

Tipo de proxy Para quais tarefas Velocidade Nível de confiança
Proxies residenciais Scraping de sites protegidos, geotargeting, monitoramento de marketplaces Média Alta — IPs residenciais reais
Proxies móveis Testes de versões móveis, trabalho com redes sociais, Facebook/TikTok API Média Máxima — IPs de operadoras
Proxies de data center Testes de integração, requisições a APIs não protegidas, alta carga Alta Média

Regra prática: se seu workflow faz scraping de Wildberries, Ozon ou outros marketplaces com proteção contra bots — use proxies residenciais. Se você está testando contas de anúncios do Facebook Ads ou TikTok Ads — use proxies móveis. Para testes de integração simples e requisições a APIs abertas, proxies de data center são suficientes: eles são mais rápidos e mais baratos.

💡 Importante sobre protocolos

Para GitHub Actions, é preferível usar proxies HTTP/HTTPS — eles são suportados pela maioria das ferramentas sem configurações adicionais. SOCKS5 também funciona, mas requer especificação explícita em cada ferramenta. Se seu provedor suporta ambos os protocolos — comece com HTTP.

Configuração de proxy através de variáveis de ambiente

A maneira mais universal de conectar um proxy no GitHub Actions é definir as variáveis de ambiente padrão HTTP_PROXY, HTTPS_PROXY e NO_PROXY. A maioria das ferramentas de linha de comando e linguagens de programação as reconhece automaticamente.

A estrutura básica de um workflow com proxy é assim:

name: Workflow com Proxy

on:
  schedule:
    - cron: '0 9 * * *'
  workflow_dispatch:

jobs:
  scrape-data:
    runs-on: ubuntu-latest

    env:
      HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      NO_PROXY: localhost,127.0.0.1,github.com

    steps:
      - name: Checkout do repositório
        uses: actions/checkout@v4

      - name: Verificar IP atual (para verificação)
        run: curl -s https://api.ipify.org

      - name: Executar script principal
        run: python scripts/scraper.py

Preste atenção ao bloco NO_PROXY — nele você deve adicionar os endereços que não precisam ter o tráfego proxy. No mínimo, isso inclui localhost e 127.0.0.1. Também é recomendável adicionar github.com, para que as operações com o repositório (checkout, push) sejam feitas diretamente.

Se o proxy não requer autenticação (apenas IP e porta), o formato se simplifica:

env:
  HTTP_PROXY: http://203.0.113.10:8080
  HTTPS_PROXY: http://203.0.113.10:8080
  NO_PROXY: localhost,127.0.0.1

Para proxies SOCKS5, apenas o esquema na URL muda:

env:
  HTTP_PROXY: socks5://user:password@proxy-host:1080
  HTTPS_PROXY: socks5://user:password@proxy-host:1080

Proxy para curl, wget e requisições HTTP no shell

Se as variáveis de ambiente estão definidas no nível do job (como mostrado acima), curl e wget as reconhecerão automaticamente. Mas às vezes é necessário passar o proxy explicitamente — por exemplo, para um passo específico ou durante a depuração.

Especificação explícita do proxy no curl:

- name: Buscar dados com proxy
  run: |
    curl -x http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }} \
      -s \
      -o output.json \
      https://api.example.com/data

    # Verificação através do proxy
    curl -x http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }} \
      -s https://api.ipify.org?format=json

Para wget:

- name: Baixar com wget via proxy
  run: |
    wget -e "https_proxy=http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}" \
      -q \
      -O data.html \
      https://target-site.com/page

Um passo útil para depuração — adicione no início do workflow uma verificação do endereço IP. Se o proxy estiver funcionando corretamente, você verá o IP do servidor proxy, e não do Azure:

- name: Verificar se o proxy está ativo
  run: |
    echo "=== IP sem proxy ==="
    curl -s --noproxy '*' https://api.ipify.org || echo "Solicitação direta falhou"
    echo ""
    echo "=== IP através do proxy ==="
    curl -s https://api.ipify.org

Proxy em scripts Python dentro do workflow

Python é uma das linguagens mais populares para scripts em CI/CD. A biblioteca requests lê automaticamente as variáveis de ambiente HTTP_PROXY e HTTPS_PROXY, se estiverem definidas. Mas para um controle mais flexível, é melhor passar o proxy explicitamente.

Exemplo de script Python com passagem explícita do proxy através de variáveis de ambiente:

import os
import requests

# Lendo dados do proxy das variáveis de ambiente
proxy_host = os.environ.get('PROXY_HOST')
proxy_port = os.environ.get('PROXY_PORT')
proxy_user = os.environ.get('PROXY_USER')
proxy_pass = os.environ.get('PROXY_PASS')

proxies = {
    'http': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}',
    'https': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}',
}

# Usando o proxy na requisição
response = requests.get(
    'https://www.wildberries.ru/catalog/123456/detail.aspx',
    proxies=proxies,
    timeout=30,
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
)

print(f"Status: {response.status_code}")
print(f"Comprimento do conteúdo: {len(response.content)}")

No arquivo do workflow, você deve passar as variáveis como segredos separados (não como uma URL completa), para que o script possa coletá-las:

- name: Executar scraper Python
  env:
    PROXY_HOST: ${{ secrets.PROXY_HOST }}
    PROXY_PORT: ${{ secrets.PROXY_PORT }}
    PROXY_USER: ${{ secrets.PROXY_USER }}
    PROXY_PASS: ${{ secrets.PROXY_PASS }}
  run: python scripts/scraper.py

Para trabalhar com Playwright ou Selenium em Python, a configuração do proxy é um pouco diferente:

# Playwright
from playwright.sync_api import sync_playwright
import os

proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": proxy_url
        }
    )
    page = browser.new_page()
    page.goto("https://target-site.com")
    # ... lógica adicional
    browser.close()

Proxy em Node.js e tarefas npm

Node.js não lê automaticamente as variáveis de sistema HTTP_PROXY — você precisa usar bibliotecas especiais ou configurar o proxy explicitamente. A opção mais conveniente é o pacote https-proxy-agent ou axios com configuração de proxy.

// Usando axios
const axios = require('axios');

const proxyConfig = {
  host: process.env.PROXY_HOST,
  port: parseInt(process.env.PROXY_PORT),
  auth: {
    username: process.env.PROXY_USER,
    password: process.env.PROXY_PASS
  }
};

async function fetchData(url) {
  try {
    const response = await axios.get(url, {
      proxy: proxyConfig,
      timeout: 30000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0)'
      }
    });
    return response.data;
  } catch (error) {
    console.error(`Solicitação falhou: ${error.message}`);
    throw error;
  }
}

fetchData('https://api.example.com/prices')
  .then(data => console.log(JSON.stringify(data, null, 2)))
  .catch(() => process.exit(1));

Para comandos npm (por exemplo, se o npm tentar baixar pacotes através de um proxy corporativo), a configuração é mais simples:

- name: Configurar proxy npm
  run: |
    npm config set proxy http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
    npm config set https-proxy http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}

- name: Instalar dependências
  run: npm install

- name: Resetar proxy npm (limpar após uso)
  run: |
    npm config delete proxy
    npm config delete https-proxy

Armazenamento seguro de dados de proxy em GitHub Secrets

Nunca armazene dados de proxy (host, porta, login, senha) diretamente no arquivo do workflow em texto claro. Isso é um erro grave de segurança: os arquivos do workflow são armazenados no repositório e podem ser visíveis para todos os participantes do projeto ou até mesmo publicamente.

A abordagem correta é usar GitHub Secrets. Aqui está um guia passo a passo:

  1. Abra o repositório no GitHub
  2. Vá para Settings → Secrets and variables → Actions
  3. Clique em New repository secret
  4. Crie quatro segredos: PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS
  5. No workflow, acesse-os através da sintaxe ${{ secrets.PROXY_HOST }}

🔒 Medidas adicionais de segurança

  • Use Environment secrets em vez de Repository secrets, se diferentes ambientes (staging/production) usarem proxies diferentes
  • Limite o acesso aos segredos através de Environment protection rules — exija confirmação manual para produção
  • Rotacione regularmente as credenciais do proxy — altere as senhas a cada 30–90 dias
  • Não exiba os valores dos segredos nos logs através de echo — o GitHub os mascara automaticamente, mas é melhor não arriscar

Se você estiver usando proxies rotativos (quando o IP muda a cada solicitação ou em um cronograma), muitas vezes é suficiente armazenar apenas um endpoint — o provedor de proxy gerencia o pool de IPs. Nesse caso, os segredos conterão apenas um host e a porta do gateway de rotação.

Rotação de proxies e tratamento de erros no pipeline

Mesmo proxies de alta qualidade podem falhar às vezes: o IP pode ser temporariamente banido, a sessão pode ser interrompida, o servidor pode não responder. Para pipelines CI/CD que funcionam automaticamente sem supervisão, é importante prever o tratamento dessas situações.

Estratégia 1: Retry com o mesmo proxy

import requests
import time
import os

def fetch_with_retry(url, max_retries=3, delay=5):
    proxies = {
        'http': f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}",
        'https': f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}",
    }

    for attempt in range(max_retries):
        try:
            response = requests.get(url, proxies=proxies, timeout=30)
            response.raise_for_status()
            return response
        except requests.exceptions.RequestException as e:
            print(f"Tentativa {attempt + 1} falhou: {e}")
            if attempt < max_retries - 1:
                print(f"Tentando novamente em {delay} segundos...")
                time.sleep(delay)
                delay *= 2  # Atraso exponencial
    raise Exception(f"Todas as {max_retries} tentativas falharam para {url}")

Estratégia 2: Lista de proxies com alternância

Se você tiver vários servidores proxy, pode armazenar a lista deles em um único segredo (separados por vírgula) e alternar em caso de erro:

import os
import requests
import random

# O segredo PROXY_LIST contém: "host1:port1:user1:pass1,host2:port2:user2:pass2"
proxy_list_raw = os.environ.get('PROXY_LIST', '').split(',')

def parse_proxy(proxy_str):
    parts = proxy_str.strip().split(':')
    if len(parts) == 4:
        host, port, user, password = parts
        return {
            'http': f'http://{user}:{password}@{host}:{port}',
            'https': f'http://{user}:{password}@{host}:{port}',
        }
    return None

proxies = [p for p in [parse_proxy(raw) for raw in proxy_list_raw] if p]

def fetch_with_proxy_rotation(url):
    random.shuffle(proxies)  # Ordem aleatória
    for proxy in proxies:
        try:
            response = requests.get(url, proxies=proxy, timeout=20)
            if response.status_code == 200:
                return response
        except Exception as e:
            print(f"Proxy falhou: {e}, tentando o próximo...")
    raise Exception("Todos os proxies foram esgotados")

Estratégia 3: Uso de endpoint rotativo

A opção mais simples é usar um provedor de proxy com um único gateway rotativo. Nesse caso, você se conecta a um único endereço, e o provedor automaticamente fornece diferentes IPs do pool. Nenhuma lógica de rotação é necessária no código — basta uma linha de conexão.

Cenários reais: scraping, testes, monitoramento de preços

Vamos considerar três cenários específicos que são mais comuns entre equipes que usam GitHub Actions com proxies.

Cenário 1: Monitoramento diário de preços no Wildberries

Vendedores de marketplaces frequentemente configuram a coleta automática de preços de concorrentes. O workflow é acionado em um cronograma (por exemplo, todas as manhãs às 7:00), coleta dados e os salva no Google Sheets ou envia para o Telegram.

name: Monitor de Preços Diário

on:
  schedule:
    - cron: '0 4 * * *'  # 07:00 MSK (UTC+3)

jobs:
  monitor-prices:
    runs-on: ubuntu-latest

    env:
      HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      NO_PROXY: github.com,api.github.com

    steps:
      - uses: actions/checkout@v4

      - name: Configurar Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Instalar dependências
        run: pip install requests beautifulsoup4 gspread

      - name: Executar scraper de preços
        env:
          GOOGLE_SHEETS_KEY: ${{ secrets.GOOGLE_SHEETS_KEY }}
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
        run: python scripts/price_monitor.py

      - name: Fazer upload do artefato de resultados
        uses: actions/upload-artifact@v4
        with:
          name: price-data-${{ github.run_id }}
          path: output/prices.json

Cenário 2: Teste geotargetizado do site

Profissionais de marketing e equipes de QA usam proxies para verificar como o site ou o anúncio aparecem para usuários de diferentes cidades. Isso é especialmente relevante para verificar preços regionais, conteúdo e redirecionamentos.

name: Testes de Site Geotargetizados

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test-moscow:
    runs-on: ubuntu-latest
    name: Teste de Moscovo
    steps:
      - uses: actions/checkout@v4
      - name: Executar testes geográficos (proxy RU/Moscovo)
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_RU_USER }}:${{ secrets.PROXY_RU_PASS }}@${{ secrets.PROXY_RU_HOST }}:${{ secrets.PROXY_RU_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_RU_USER }}:${{ secrets.PROXY_RU_PASS }}@${{ secrets.PROXY_RU_HOST }}:${{ secrets.PROXY_RU_PORT }}
        run: |
          python tests/geo_test.py --region=RU --city=Moscow

  test-germany:
    runs-on: ubuntu-latest
    name: Teste da Alemanha
    steps:
      - uses: actions/checkout@v4
      - name: Executar testes geográficos (proxy DE)
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_DE_USER }}:${{ secrets.PROXY_DE_PASS }}@${{ secrets.PROXY_DE_HOST }}:${{ secrets.PROXY_DE_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_DE_USER }}:${{ secrets.PROXY_DE_PASS }}@${{ secrets.PROXY_DE_HOST }}:${{ secrets.PROXY_DE_PORT }}
        run: |
          python tests/geo_test.py --region=DE

Cenário 3: Verificação automática de contas de anúncios

Arbitradores e profissionais de marketing de performance frequentemente usam GitHub Actions para verificar automaticamente o status das contas de anúncios do Facebook Ads, saldos e métricas. Solicitações à Facebook Marketing API de faixas do Azure podem acionar verificações de segurança adicionais — o proxy ajuda a contornar isso.

name: Verificação de Saúde da Conta de Anúncios

on:
  schedule:
    - cron: '*/30 6-22 * * *'  # A cada 30 minutos das 6 às 22 MSK

jobs:
  check-accounts:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Configurar Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Instalar dependências
        run: pip install requests

      - name: Verificar contas do Facebook Ads
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
          FB_ACCESS_TOKEN: ${{ secrets.FB_ACCESS_TOKEN }}
          ACCOUNT_IDS: ${{ secrets.FB_ACCOUNT_IDS }}
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
        run: python scripts/check_fb_accounts.py

📋 Checklist antes de executar o workflow com proxy

  • ✅ Dados do proxy adicionados ao GitHub Secrets (não no arquivo do workflow)
  • ✅ Variáveis NO_PROXY incluem github.com
  • ✅ Passo de verificação de IP adicionado para depuração
  • ✅ Tratamento de erros e lógica de retry implementados
  • ✅ Tipo de proxy corresponde à tarefa (residenciais para sites protegidos)
  • ✅ Notificações de erro configuradas (Telegram, Slack ou email)
  • ✅ Workflow testado manualmente através de workflow_dispatch antes de adicionar o cronograma

Conclusão

Configurar um proxy no GitHub Actions não é uma tarefa difícil se você souber a abordagem correta. As principais conclusões deste guia são:

  • Variáveis de ambiente HTTP_PROXY / HTTPS_PROXY — uma maneira universal que funciona para a maioria das ferramentas sem alteração de código.
  • GitHub Secrets — o único lugar correto para armazenar credenciais de proxy.
  • O tipo de proxy é importante: para scraping de marketplaces protegidos, são necessários IPs residenciais, para plataformas de anúncios — móveis, para requisições simples de API, proxies de data center são suficientes.
  • Lógica de retry é obrigatória para pipelines que funcionam sem supervisão em um cronograma.
  • Um passo de verificação de IP no início do workflow economizará horas de depuração.

Se seu workflow do GitHub Actions trabalha com marketplaces, plataformas de anúncios ou qualquer serviço com proteção contra bots, recomendamos usar proxies residenciais — eles têm IPs reais de usuários domésticos e raramente causam bloqueios em comparação com endereços em nuvem dos servidores do GitHub. Para tarefas relacionadas ao Facebook Ads, TikTok ou outras plataformas sociais, a escolha ideal são proxies móveis com IPs de operadoras — eles oferecem o máximo nível de confiança por parte das plataformas.

```