Tutorials

Protegendo credenciais CaptchaAI em variáveis de ambiente

A regra é simples: a chave de API da CaptchaAI nunca deve aparecer em um arquivo .py, .js ou .yml versionado. Ela mora em uma variável de ambiente, lida pelo código na hora de subir — vale para o script no seu notebook e para o worker em produção.

O motivo não é teórico. Bots varrem repositórios públicos atrás de padrões de credenciais, e um repositório interno que muda de visibilidade por engano expõe todo o histórico de commits de uma vez. Como a CaptchaAI cobra por thread simultânea e não por resolução, uma chave vazada não gera fatura surpresa — ela consome as threads do seu plano. No BASIC (US$ 15/mês, 5 threads), bastam cinco requisições de terceiros em paralelo para o seu processo ficar esperando na fila.

Este tutorial percorre as quatro camadas — .env local, sistema, containers e CI/CD — e fecha com a validação de inicialização.


Escolha a camada certa para cada ambiente

Antes do código, decida onde a chave vai viver em cada estágio. As camadas não competem: elas se empilham conforme o ambiente fica mais compartilhado.

Ambiente Onde guardar Quem enxerga a chave
Máquina do desenvolvedor arquivo .env ignorado pelo Git apenas o dono da máquina
Servidor ou VM dedicada variável de ambiente do sistema operacional quem tem shell no host
Container variável injetada em runtime ou Docker secret o processo dentro do container
CI/CD e produção cofre do provedor (GitHub Actions, GitLab, AWS Secrets Manager, Azure Key Vault) somente o job em execução

O erro clássico

Levar o .env local para o servidor de produção "só por enquanto": esse arquivo sobrevive a deploys, entra em backups e acaba copiado para outro host meses depois.


Uma chave por ambiente: LGPD e times distribuídos

Times brasileiros que rodam automação autorizada — QA em homologação, monitoramento próprio, testes de endpoints internos — costumam compartilhar um único .env por mensagem quando o time cresce rápido. Isso atrapalha a rastreabilidade exigida por políticas internas alinhadas à LGPD: sem chave por ambiente e sem registro de acesso, não dá para dizer de onde partiu uma requisição.

A separação mínima que funciona:

  • uma chave para a máquina do desenvolvedor;
  • uma chave para o CI, cadastrada no cofre do provedor;
  • uma chave de produção, que ninguém copia para o notebook.

Se você mantém workers em sa-east-1, injete a variável pela definição da tarefa, não pela imagem: assim a troca da chave dispensa um novo build.


Erros comuns que expõem a chave

Erro Risco Correção
Commitar o .env Chave permanente no histórico do repositório Coloque .env no .gitignore antes do primeiro commit
Imprimir a chave nos logs Chave replicada em agregadores e backups Nunca registre a chave inteira; mascare os caracteres finais
Fixar a chave no Dockerfile Chave gravada nas camadas da imagem Use ENV em runtime, nunca em estágio de build
Enviar a chave por chat ou e-mail Cópia fora de controle, sem expiração Compartilhe por um gerenciador de segredos
Reaproveitar a mesma chave em QA e produção Um incidente derruba os dois ambientes Chaves separadas por ambiente

Passo 1: arquivo .env no ambiente local

Crie um arquivo .env na raiz do projeto:

CAPTCHAAI_API_KEY=your_actual_api_key_here

Adicione o arquivo ao .gitignore antes do primeiro commit — depois de commitado, ele permanece no histórico mesmo que você o apague:

# .gitignore
.env
.env.local
.env.production

Python com python-dotenv

pip install python-dotenv
import os
from dotenv import load_dotenv

load_dotenv()

API_KEY = os.environ["CAPTCHAAI_API_KEY"]

# Use in API calls
import requests
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": "6Le-SITEKEY",
    "pageurl": "https://example.com",
    "json": "1",
})
print(resp.json())

Repare nos colchetes em os.environ["CAPTCHAAI_API_KEY"]: sem a variável, o script falha na hora, em vez de enviar uma requisição vazia e devolver um erro de autenticação obscuro.

Node.js com dotenv

npm install dotenv
require('dotenv').config();

const API_KEY = process.env.CAPTCHAAI_API_KEY;

if (!API_KEY) {
  console.error('CAPTCHAAI_API_KEY not set');
  process.exit(1);
}

// Use in API calls
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: {
    key: API_KEY,
    method: 'userrecaptcha',
    googlekey: '6Le-SITEKEY',
    pageurl: 'https://example.com',
    json: 1,
  },
});
console.log(resp.data);

Em Node.js, process.env devolve undefined silenciosamente. Daí a verificação explícita: é a diferença entre uma mensagem clara no log e um 401 genérico às três da manhã.


Passo 2: variáveis no nível do sistema operacional

Linux e macOS

export CAPTCHAAI_API_KEY="your_actual_api_key_here"

# Persist across sessions — add to ~/.bashrc or ~/.zshrc
echo 'export CAPTCHAAI_API_KEY="your_actual_api_key_here"' >> ~/.bashrc

Windows com PowerShell

$env:CAPTCHAAI_API_KEY = "your_actual_api_key_here"

# Persist permanently
[System.Environment]::SetEnvironmentVariable("CAPTCHAAI_API_KEY", "your_actual_api_key_here", "User")

Dois cuidados valem nos dois sistemas:

  • o histórico do shell guarda o comando digitado, com a chave inteira;
  • em máquina compartilhada, edite o arquivo de perfil num editor em vez de usar echo.

Passo 3: containers Docker

Injetando a variável no docker run

docker run -e CAPTCHAAI_API_KEY="your_key" my-scraper

Referenciando o valor no docker-compose

# docker-compose.yml
services:
  scraper:
    image: my-scraper
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
  • ${CAPTCHAAI_API_KEY} aponta para a variável já definida no host;
  • a chave nunca entra no arquivo de composição, que costuma ser versionado.

Docker secrets em modo Swarm

echo "your_actual_api_key_here" | docker secret create captchaai_key -
# docker-compose.yml (Swarm mode)
services:
  scraper:
    image: my-scraper
    secrets:

      - captchaai_key
secrets:
  captchaai_key:
    external: true

O segredo é montado como arquivo dentro do container e lido no código:

with open("/run/secrets/captchaai_key") as f:
    API_KEY = f.read().strip()

Passo 4: pipelines de CI/CD

GitHub Actions

# .github/workflows/scrape.yml
jobs:
  scrape:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4
      - run: python scraper.py
        env:
          CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
  • Cadastre o valor em Settings → Secrets and variables → Actions → New repository secret.
  • O runner mascara o segredo no log do job, mas não em arquivos que o seu script gravar.

GitLab CI

# .gitlab-ci.yml
scrape:
  script:

    - python scraper.py
  variables:
    CAPTCHAAI_API_KEY: $CAPTCHAAI_API_KEY
  • Cadastre a variável em Settings → CI/CD → Variables com a opção "Masked" habilitada.
  • Sem o mascaramento, um echo acidental imprime a chave no log, visível a todo o time.

Passo 5: valide a chave na inicialização

Verificar a chave no start custa uma requisição e economiza horas de diagnóstico:

import os
import sys
import requests

API_KEY = os.environ.get("CAPTCHAAI_API_KEY")
if not API_KEY:
    print("ERROR: CAPTCHAAI_API_KEY environment variable not set")
    sys.exit(1)

# Verify key works
resp = requests.get("https://ocr.captchaai.com/res.php", params={
    "key": API_KEY, "action": "getbalance", "json": "1"
}).json()

if resp["status"] != 1:
    print(f"ERROR: Invalid API key — {resp['request']}")
    sys.exit(1)

print(f"API key valid — balance: ${float(resp['request']):.2f}")

Quando a checagem passa no seu terminal e falha no servidor

O problema costuma ser de contexto, não da chave:

  • a variável existe no shell interativo, mas não no serviço systemd que sobe o worker;
  • o container recebeu a imagem, e não a variável do host;
  • o job de CI procura um segredo com outro nome.

Perguntas frequentes

Preciso de chaves diferentes para staging e produção?

Sim, sempre que possível. Chaves separadas permitem revogar um ambiente sem parar o outro e mostram no painel qual deles consumiu as threads do plano.

Como evito que a chave apareça nos logs?

Nunca imprima a variável. Três hábitos resolvem:

  • registre no máximo os quatro últimos caracteres;
  • mantenha o mascaramento nativo do CI habilitado;
  • filtre exceções que carreguem o corpo da requisição.

Variáveis de ambiente funcionam em funções serverless?

Funcionam. AWS Lambda, Azure Functions e Google Cloud Functions expõem variáveis definidas no console ou no template de deploy — e todas leem de um cofre gerenciado.

A chave está ligada ao plano contratado?

Sim. A chave identifica a conta, e o plano define quantas threads simultâneas ela pode usar — de BASIC (US$ 15/mês, 5 threads) a VIP-3 (US$ 7.500/mês, 5.000 threads), com resoluções ilimitadas por thread. Por isso um vazamento aparece primeiro como fila, não como cobrança extra.

Posso usar várias chaves da CaptchaAI no mesmo .env?

Sim. Use valores separados por vírgula ou chaves numeradas:

CAPTCHAAI_KEYS=key1,key2,key3
keys = os.environ["CAPTCHAAI_KEYS"].split(",")

Comece com a credencial no lugar certo

Gere sua chave em captchaai.com, configure a variável de ambiente antes da primeira integração e mantenha o repositório limpo desde o commit inicial.


Guias relacionados

Os comentários estão desativados para este artigo.