Raspagem de APIs GraphQL protegidas: burlar limites, APQ e impressão digital de TLS

Raspagem de APIs GraphQL protegidas: burlar limites, APQ e impressão digital de TLS
Markus_automation
Markus_automation

Expert in data parsing and automation

Ao coletar dados de recursos modernos da web — especialmente de plataformas de mídia social e grandes aplicativos web — simplesmente solicitar páginas HTML com requisições GET não é mais suficiente. A maioria das grandes plataformas mudou para interfaces dinâmicas e APIs, com o GraphQL se tornando uma das tecnologias mais amplamente adotadas.

Por um lado, o GraphQL permite recuperar dados relacionados por meio de um único ponto de entrada em vez de consultar vários endpoints REST separados. Em vez de enviar uma cadeia de requisições, você pode criar uma única consulta e especificar exatamente quais dados precisa.

Por outro lado, essa arquitetura torna o endpoint do GraphQL o ponto de interação central entre o cliente e o servidor. Como resultado, ele se tornou o foco principal de atenção dos sistemas anti-bot. Onde antes os mecanismos de proteção analisavam muitas requisições diferentes, agora eles concentram grande parte de sua lógica de controle no conteúdo, estrutura, frequência e comportamento das consultas GraphQL.

Para entender por que o GraphQL é ao mesmo tempo conveniente para raspagem de dados e interessante do ponto de vista da segurança, vamos primeiro examinar como ele funciona.

Índice

Mantenha o anonimato, aproveite o recurso multiconta e alcance seus objetivos com o melhor navegador antidetecção do mercado.

Gostaria de experimentar o Octo Browser com desconto?
Use o código promocional OCTOSCRAPER para obter 30% de desconto em qualquer assinatura. Esta oferta é válida apenas para novos usuários.

O problema do endpoint único

Na arquitetura REST tradicional, o roteamento ajuda a distribuir a carga e aplicar diferentes limites de taxa. Por exemplo, o endpoint /api/users pode ter um conjunto de restrições, enquanto /api/feed tem outro.

Com o GraphQL, há apenas um endpoint. Todos os dados úteis são enviados no corpo de uma requisição POST como JSON contendo a consulta, as variáveis e o nome da operação. No nível HTTP, parece algo assim:

{
  "operationName": null,
  "variables": {},
  "query": "query { users { id name posts(last: 5) { id text timestamp } } }"
}
{
  "operationName": null,
  "variables": {},
  "query": "query { users { id name posts(last: 5) { id text timestamp } } }"
}

Para fins de legibilidade, no entanto, estamos acostumados a ver a mesma requisição em sua forma gráfica expandida:

query {
 users {
   id
   name
   posts(last: 5) {
     id
     text
     timestamp
   }
 }
}
query {
 users {
   id
   name
   posts(last: 5) {
     id
     text
     timestamp
   }
 }
}

Isso significa que, sob a perspectiva de balanceadores de carga e sistemas básicos de segurança, cada requisição parece ser uma chamada idêntica para a mesma URL.

Para determinar o que o cliente está realmente fazendo, os sistemas antibot tentam inspecionar o payload JSON em tempo real, enquanto o servidor de aplicação analisa a pesada AST (Abstract Syntax Tree) resultante.

As estratégias modernas de scraping e proteção são construídas exatamente em torno dessa característica arquitetural.

O que fazer quando a Introspecção está desativada

Antes de desenvolver um scraper, determine exatamente como funciona o sistema antibot do site alvo. A análise de GraphQL geralmente começa tentando uma consulta de Introspection. Esse recurso integrado instrui o servidor a retornar a documentação completa da API, incluindo todos os tipos, campos, relacionamentos e argumentos.

What to do when Introspection is disabled

Naturalmente, plataformas sérias restringem o acesso a essas informações. Mesmo assim, ainda existem maneiras de obtê-las.

  • Analise as mensagens de erro. Muitos servidores GraphQL tentam ajudar os usuários por padrão. Por exemplo, se você solicitar um campo inexistente chamado nam, o servidor poderá retornar um erro como "Cannot query field "nam". Did you mean "name"?". Esse processo pode ser automatizado para reconstruir gradualmente uma parte significativa do esquema oculto.

  • Procure por vazamentos de middleware. A consulta de Introspection costuma ser desativada no servidor de aplicação primário, mas acidentalmente deixada ativada em microsserviços ou em API gateways que são diretamente acessíveis.

O scraping sempre exige improvisação. Procure caminhos alternativos, pois eles costumam ser deixados desprotegidos.

Consultas Persistidas Automáticas (APQ)

Suponha que você tenha reconstruído o esquema com sucesso, compreendido a estrutura dos dados e construído sua consulta GraphQL. Em vez de enviar dados, no entanto, o servidor retorna um erro de validação. Isso é o APQ funcionando.

Para evitar o envio repetido de consultas gráficas grandes pela rede, os desenvolvedores introduziram as Consultas Persistidas Automáticas (APQ). Essa otimização de GraphQL permite que o cliente envie um hash (um identificador único de consulta) em vez do texto completo da consulta. Isso reduz significativamente o tamanho da requisição, acelera a transmissão e permite que as consultas sejam armazenadas em cache em uma CDN.

Veja como funciona para um cliente típico: em vez de enviar a consulta completa, o frontend calcula seu hash SHA-256 e envia apenas o hash com as variáveis da consulta. O servidor verifica seu cache e, se o hash for reconhecido, executa a consulta associada.

For example, Reddit's frontend doesn't send the query body at all. Instead, it sends only the pre-registered operation name (operation: "ExposeVariant") along with the required variables

Por exemplo, o frontend do Reddit não envia o corpo da consulta de forma alguma. Em vez disso, ele envia apenas o nome da operação pré-registrada (operation: "ExposeVariant") com as variáveis necessárias

Por que isso complica o scraping: você não pode simplesmente escrever sua própria consulta personalizada em um script e enviá-la ao servidor. O servidor espera um hash de 64 caracteres. Se você enviar sua consulta em texto simples, receberá um erro de validação.

Maneiras de contornar isso:

  1. Análise de recursos estáticos. Todos os hashes legítimos são incorporados nos pacotes de JavaScript compilados do frontend. Um script de scraping automatizado deve primeiro baixar esses arquivos JS, extrair os mapeamentos de hash para consulta e só então construir um banco de dados antes de emitir as requisições reais.

  2. Requisições de fallback. O APQ foi projetado de modo que, se o servidor não reconhecer um hash, o cliente reenvie tanto o hash quanto a consulta completa. Muitos servidores deixam esse comportamento habilitado, permitindo que um scraper registre dinamicamente consultas arbitrárias — mesmo aquelas nunca planejadas pelo frontend.

Ofuscação da camada de transporte (TLS fingerprinting)

Para evitar queimar seu pool de proxies, preste atenção na camada de transporte. Comece sua falsificação garantindo que o handshake TLS esteja devidamente formatado.

O TLS (Transport Layer Security) é um protocolo que estabelece conexões seguras. Durante o handshake, o cliente envia uma mensagem ClientHello contendo um conjunto de parâmetros de criptografia. Esses parâmetros revelam muito sobre você ao servidor.

Sistemas de proteção como Cloudflare, Akamai e DataDome analisam essas impressões digitais de rede. Bibliotecas padrão como a requests do Python ou o axios do Node.js possuem assinaturas altamente reconhecíveis que diferem das de um Google Chrome ou Safari reais, pois enviam uma ordem diferente de suítes de cifras, versões de protocolo e extensões no pacote ClientHello.

Existem duas abordagens principais para coleta de dados em larga escala:

  1. Bibliotecas especializadas. Substitua os clientes HTTP padrão por bibliotecas capazes de emular a impressão digital de TLS, como curl-cffi para Python ou tls-client para Go. Essas ferramentas imitam o comportamento do navegador no nível da requisição, mantendo um alto desempenho.

  2. Navegadores antidetecção. Se a plataforma de destino tiver uma proteção particularmente agressiva, você pode usar um navegador antidetecção avançado, como o Octo Browser. Nesse caso, a falsificação da impressão digital do TLS ocorre no nível do núcleo do navegador. Embora essa abordagem seja um pouco mais lenta, ela também é a mais confiável. O servidor vê um comportamento indistinguível daquele de um navegador real, minimizando o risco de detecção e bloqueios.

Contornando o limite de taxa (rate limiting)

Assim que seu scraper estiver funcionando, você poderá encontrar outra camada de proteção: o limite de taxa.

Com as APIs REST, os sistemas de proteção normalmente contam o número de requisições HTTP por segundo de um único endereço IP. O GraphQL, no entanto, permite que uma única requisição HTTP recupere uma quantidade enorme de dados relacionados. Os scrapers costumam aproveitar duas funcionalidades nativas do GraphQL para contornar os contadores de requisição tradicionais:

  • Requisições em lote (batching). Originalmente, o envio em lote foi introduzido para que o frontend pudesse combinar várias requisições independentes de API em um único array JSON e enviá-las juntas. Para um scraper, isso significa que, em vez de fazer 100 requisições separadas para recuperar 100 perfis de usuário, você pode enviar uma única requisição contendo um array de 100 objetos de operação. Se o limitador de taxa apenas analisar o tráfego no nível HTTP, ele considerará isso como apenas uma requisição.

  • Aliases. Se o servidor bloquear o lote de JSON, você poderá usar outro recurso do GraphQL: os aliases. Os aliases permitem solicitar o mesmo campo várias vezes com argumentos diferentes em uma única operação. Isso aumenta a carga no banco de dados do servidor, mas para o firewall da rede ainda parecerá uma única requisição legítima.

query GetMultipleUsers {
  user_1: user(id: "1001") { name, email }
  user_2: user(id: "1002") { name, email }
  # e assim por diante
}
query GetMultipleUsers {
  user_1: user(id: "1001") { name, email }
  user_2: user(id: "1002") { name, email }
  # e assim por diante
}

No entanto, é importante entender que hoje nem o loteamento nem os aliases garantem a resolução do problema.

Em vez de apenas contar requisições, muitas plataformas agora implementam a Análise de Custo de Consulta (Query Cost Analysis). Cada campo e relacionamento no esquema recebe um peso. Um campo escalar simples, como name, pode custar um ponto, enquanto solicitar uma lista aninhada como posts(last: 100) pode custar dez pontos.

Antes de executar sua consulta, o servidor a analisa, calcula seu custo total e a rejeita com um erro como "Max query complexity exceeded" se o total exceder o limite pré-configurado — por exemplo, se 500 aliases passarem a consulta de um limite de 1.000 pontos.

Sistemas de proteção também aplicam limites rígidos à profundidade de aninhamento da consulta. Se um scraper tentar, em uma única consulta, recuperar um grafo recursivo de relacionamentos — como user → seus amigos → posts dos amigos → comentários nos posts —, ele quase certamente atingirá o limite pré-configurado de profundidade de aninhamento.

Como lidar com isso: em vez de tentar encontrar o tamanho ideal para uma consulta profunda — por exemplo, dividindo-a em lotes de 20 a 30 aliases em vez de 500 —, geralmente é melhor redesenhar o scraper em torno de uma estratégia de busca plana.

  1. Consultas planas. Comece com uma consulta leve de nível superior que recupere apenas uma lista plana de IDs dos objetos necessários, sem seus relacionamentos.

  2. Divisão em pedaços (chunking) e workers. Divida os IDs recuperados em lotes pequenos e seguros (chunks). Em seguida, use um conjunto de workers para obter informações detalhadas para esses IDs em paralelo.

  3. Reconstrução local do grafo. Reconstrua a estrutura relacional do lado do scraper. Armazene os dados localmente (ou em um banco de dados intermediário) e mescle-os programaticamente.

Essa abordagem requer lógica de orquestração adicional e armazenamento em cache local. Em contrapartida, ela proporciona um scraping estável e multithread sem disparar regras de WAF, banimentos temporários (shadow bans) ou tempos limite (timeouts) de banco de dados na plataforma de destino.

Conclusão

Fazer scraping em APIs GraphQL modernas exige uma interação completa com sistemas distribuídos complexos, incluindo considerações na camada de transporte — como emulação de TLS —, além de uma compreensão do processamento de AST e dos mecanismos de cache do lado do servidor.

Os sistemas de proteção continuam a evoluir, mas a flexibilidade arquitetônica que torna o GraphQL tão atraente para os desenvolvedores também deixa muitas oportunidades para sistemas de coleta de dados bem projetados.

Mantenha o anonimato, aproveite o recurso multiconta e alcance seus objetivos com o melhor navegador antidetecção do mercado.

Gostaria de experimentar o Octo Browser com desconto?
Use o código promocional OCTOSCRAPER para obter 30% de desconto em qualquer assinatura. Esta oferta é válida apenas para novos usuários.

O problema do endpoint único

Na arquitetura REST tradicional, o roteamento ajuda a distribuir a carga e aplicar diferentes limites de taxa. Por exemplo, o endpoint /api/users pode ter um conjunto de restrições, enquanto /api/feed tem outro.

Com o GraphQL, há apenas um endpoint. Todos os dados úteis são enviados no corpo de uma requisição POST como JSON contendo a consulta, as variáveis e o nome da operação. No nível HTTP, parece algo assim:

{
  "operationName": null,
  "variables": {},
  "query": "query { users { id name posts(last: 5) { id text timestamp } } }"
}

Para fins de legibilidade, no entanto, estamos acostumados a ver a mesma requisição em sua forma gráfica expandida:

query {
 users {
   id
   name
   posts(last: 5) {
     id
     text
     timestamp
   }
 }
}

Isso significa que, sob a perspectiva de balanceadores de carga e sistemas básicos de segurança, cada requisição parece ser uma chamada idêntica para a mesma URL.

Para determinar o que o cliente está realmente fazendo, os sistemas antibot tentam inspecionar o payload JSON em tempo real, enquanto o servidor de aplicação analisa a pesada AST (Abstract Syntax Tree) resultante.

As estratégias modernas de scraping e proteção são construídas exatamente em torno dessa característica arquitetural.

O que fazer quando a Introspecção está desativada

Antes de desenvolver um scraper, determine exatamente como funciona o sistema antibot do site alvo. A análise de GraphQL geralmente começa tentando uma consulta de Introspection. Esse recurso integrado instrui o servidor a retornar a documentação completa da API, incluindo todos os tipos, campos, relacionamentos e argumentos.

What to do when Introspection is disabled

Naturalmente, plataformas sérias restringem o acesso a essas informações. Mesmo assim, ainda existem maneiras de obtê-las.

  • Analise as mensagens de erro. Muitos servidores GraphQL tentam ajudar os usuários por padrão. Por exemplo, se você solicitar um campo inexistente chamado nam, o servidor poderá retornar um erro como "Cannot query field "nam". Did you mean "name"?". Esse processo pode ser automatizado para reconstruir gradualmente uma parte significativa do esquema oculto.

  • Procure por vazamentos de middleware. A consulta de Introspection costuma ser desativada no servidor de aplicação primário, mas acidentalmente deixada ativada em microsserviços ou em API gateways que são diretamente acessíveis.

O scraping sempre exige improvisação. Procure caminhos alternativos, pois eles costumam ser deixados desprotegidos.

Consultas Persistidas Automáticas (APQ)

Suponha que você tenha reconstruído o esquema com sucesso, compreendido a estrutura dos dados e construído sua consulta GraphQL. Em vez de enviar dados, no entanto, o servidor retorna um erro de validação. Isso é o APQ funcionando.

Para evitar o envio repetido de consultas gráficas grandes pela rede, os desenvolvedores introduziram as Consultas Persistidas Automáticas (APQ). Essa otimização de GraphQL permite que o cliente envie um hash (um identificador único de consulta) em vez do texto completo da consulta. Isso reduz significativamente o tamanho da requisição, acelera a transmissão e permite que as consultas sejam armazenadas em cache em uma CDN.

Veja como funciona para um cliente típico: em vez de enviar a consulta completa, o frontend calcula seu hash SHA-256 e envia apenas o hash com as variáveis da consulta. O servidor verifica seu cache e, se o hash for reconhecido, executa a consulta associada.

For example, Reddit's frontend doesn't send the query body at all. Instead, it sends only the pre-registered operation name (operation: "ExposeVariant") along with the required variables

Por exemplo, o frontend do Reddit não envia o corpo da consulta de forma alguma. Em vez disso, ele envia apenas o nome da operação pré-registrada (operation: "ExposeVariant") com as variáveis necessárias

Por que isso complica o scraping: você não pode simplesmente escrever sua própria consulta personalizada em um script e enviá-la ao servidor. O servidor espera um hash de 64 caracteres. Se você enviar sua consulta em texto simples, receberá um erro de validação.

Maneiras de contornar isso:

  1. Análise de recursos estáticos. Todos os hashes legítimos são incorporados nos pacotes de JavaScript compilados do frontend. Um script de scraping automatizado deve primeiro baixar esses arquivos JS, extrair os mapeamentos de hash para consulta e só então construir um banco de dados antes de emitir as requisições reais.

  2. Requisições de fallback. O APQ foi projetado de modo que, se o servidor não reconhecer um hash, o cliente reenvie tanto o hash quanto a consulta completa. Muitos servidores deixam esse comportamento habilitado, permitindo que um scraper registre dinamicamente consultas arbitrárias — mesmo aquelas nunca planejadas pelo frontend.

Ofuscação da camada de transporte (TLS fingerprinting)

Para evitar queimar seu pool de proxies, preste atenção na camada de transporte. Comece sua falsificação garantindo que o handshake TLS esteja devidamente formatado.

O TLS (Transport Layer Security) é um protocolo que estabelece conexões seguras. Durante o handshake, o cliente envia uma mensagem ClientHello contendo um conjunto de parâmetros de criptografia. Esses parâmetros revelam muito sobre você ao servidor.

Sistemas de proteção como Cloudflare, Akamai e DataDome analisam essas impressões digitais de rede. Bibliotecas padrão como a requests do Python ou o axios do Node.js possuem assinaturas altamente reconhecíveis que diferem das de um Google Chrome ou Safari reais, pois enviam uma ordem diferente de suítes de cifras, versões de protocolo e extensões no pacote ClientHello.

Existem duas abordagens principais para coleta de dados em larga escala:

  1. Bibliotecas especializadas. Substitua os clientes HTTP padrão por bibliotecas capazes de emular a impressão digital de TLS, como curl-cffi para Python ou tls-client para Go. Essas ferramentas imitam o comportamento do navegador no nível da requisição, mantendo um alto desempenho.

  2. Navegadores antidetecção. Se a plataforma de destino tiver uma proteção particularmente agressiva, você pode usar um navegador antidetecção avançado, como o Octo Browser. Nesse caso, a falsificação da impressão digital do TLS ocorre no nível do núcleo do navegador. Embora essa abordagem seja um pouco mais lenta, ela também é a mais confiável. O servidor vê um comportamento indistinguível daquele de um navegador real, minimizando o risco de detecção e bloqueios.

Contornando o limite de taxa (rate limiting)

Assim que seu scraper estiver funcionando, você poderá encontrar outra camada de proteção: o limite de taxa.

Com as APIs REST, os sistemas de proteção normalmente contam o número de requisições HTTP por segundo de um único endereço IP. O GraphQL, no entanto, permite que uma única requisição HTTP recupere uma quantidade enorme de dados relacionados. Os scrapers costumam aproveitar duas funcionalidades nativas do GraphQL para contornar os contadores de requisição tradicionais:

  • Requisições em lote (batching). Originalmente, o envio em lote foi introduzido para que o frontend pudesse combinar várias requisições independentes de API em um único array JSON e enviá-las juntas. Para um scraper, isso significa que, em vez de fazer 100 requisições separadas para recuperar 100 perfis de usuário, você pode enviar uma única requisição contendo um array de 100 objetos de operação. Se o limitador de taxa apenas analisar o tráfego no nível HTTP, ele considerará isso como apenas uma requisição.

  • Aliases. Se o servidor bloquear o lote de JSON, você poderá usar outro recurso do GraphQL: os aliases. Os aliases permitem solicitar o mesmo campo várias vezes com argumentos diferentes em uma única operação. Isso aumenta a carga no banco de dados do servidor, mas para o firewall da rede ainda parecerá uma única requisição legítima.

query GetMultipleUsers {
  user_1: user(id: "1001") { name, email }
  user_2: user(id: "1002") { name, email }
  # e assim por diante
}

No entanto, é importante entender que hoje nem o loteamento nem os aliases garantem a resolução do problema.

Em vez de apenas contar requisições, muitas plataformas agora implementam a Análise de Custo de Consulta (Query Cost Analysis). Cada campo e relacionamento no esquema recebe um peso. Um campo escalar simples, como name, pode custar um ponto, enquanto solicitar uma lista aninhada como posts(last: 100) pode custar dez pontos.

Antes de executar sua consulta, o servidor a analisa, calcula seu custo total e a rejeita com um erro como "Max query complexity exceeded" se o total exceder o limite pré-configurado — por exemplo, se 500 aliases passarem a consulta de um limite de 1.000 pontos.

Sistemas de proteção também aplicam limites rígidos à profundidade de aninhamento da consulta. Se um scraper tentar, em uma única consulta, recuperar um grafo recursivo de relacionamentos — como user → seus amigos → posts dos amigos → comentários nos posts —, ele quase certamente atingirá o limite pré-configurado de profundidade de aninhamento.

Como lidar com isso: em vez de tentar encontrar o tamanho ideal para uma consulta profunda — por exemplo, dividindo-a em lotes de 20 a 30 aliases em vez de 500 —, geralmente é melhor redesenhar o scraper em torno de uma estratégia de busca plana.

  1. Consultas planas. Comece com uma consulta leve de nível superior que recupere apenas uma lista plana de IDs dos objetos necessários, sem seus relacionamentos.

  2. Divisão em pedaços (chunking) e workers. Divida os IDs recuperados em lotes pequenos e seguros (chunks). Em seguida, use um conjunto de workers para obter informações detalhadas para esses IDs em paralelo.

  3. Reconstrução local do grafo. Reconstrua a estrutura relacional do lado do scraper. Armazene os dados localmente (ou em um banco de dados intermediário) e mescle-os programaticamente.

Essa abordagem requer lógica de orquestração adicional e armazenamento em cache local. Em contrapartida, ela proporciona um scraping estável e multithread sem disparar regras de WAF, banimentos temporários (shadow bans) ou tempos limite (timeouts) de banco de dados na plataforma de destino.

Conclusão

Fazer scraping em APIs GraphQL modernas exige uma interação completa com sistemas distribuídos complexos, incluindo considerações na camada de transporte — como emulação de TLS —, além de uma compreensão do processamento de AST e dos mecanismos de cache do lado do servidor.

Os sistemas de proteção continuam a evoluir, mas a flexibilidade arquitetônica que torna o GraphQL tão atraente para os desenvolvedores também deixa muitas oportunidades para sistemas de coleta de dados bem projetados.

Mantenha-se atualizado com as últimas notícias do Octo Browser

Ao clicar no botão, você concorda com a nossa Política de Privacidade.

Mantenha-se atualizado com as últimas notícias do Octo Browser

Ao clicar no botão, você concorda com a nossa Política de Privacidade.

Mantenha-se atualizado com as últimas notícias do Octo Browser

Ao clicar no botão, você concorda com a nossa Política de Privacidade.

Junte-se ao Octo Browser agora mesmo

Ou entre em contato com a equipe de suporte no chat para tirar dúvidas a qualquer momento.

Junte-se ao Octo Browser agora mesmo

Ou entre em contato com a equipe de suporte no chat para tirar dúvidas a qualquer momento.

Junte-se ao Octo Browser agora mesmo

Ou entre em contato com a equipe de suporte no chat para tirar dúvidas a qualquer momento.

©

2026

Octo Browser

©

2026

Octo Browser

©

2026

Octo Browser