Ir para o conteúdo

Mapa

Pegue todas as URLs que um site lista com uma chamada só, sem abrir as páginas. A lista sai do robots.txt do site, dos sitemaps dele e dos links da página que você passar.

Uma chamada

POST /v1/map
curl -X POST https://api.scrapa.app/v1/map \
  -H "authorization: Bearer sc_live_your_key" \
  -H "content-type: application/json" \
  -d '{"url": "https://example.com"}'
A resposta
{
  "data": {
    "urls": [
      { "url": "https://example.com", "lastmod": "2026-10-01" },
      { "url": "https://example.com/pricing", "lastmod": "2026-09-12" },
      { "url": "https://example.com/blog/hello" }
    ],
    "source": "both",
    "truncated": false,
    "pool": "residential",
    "bytes": 48211
  },
  "meta": { "cost": 2, "creditsRemaining": 985, "requestId": "0f3c…" }
}

Você manda o endereço do site e a gente devolve as URLs dele, cada uma uma vez só, com a data da última alteração quando o sitemap informa.

De onde vêm as URLs

Primeiro o robots.txt do site, que aponta os sitemaps. Depois os três lugares onde os sites costumam guardar um: /sitemap.xml, /sitemap_index.xml e /sitemap.txt. Quando um sitemap lista outros sitemaps, a gente segue, e quando vem compactado em gzip, a gente descompacta. Ao mesmo tempo, a gente lê a página que você passou e guarda os links dela.

O sitemap escolhe as fontes. include, o padrão, lê as duas. only lê só os sitemaps. skip lê só os links da página, para um site sem sitemap.

Só as URLs que você quer

search, includeSubdomains
{
  "url": "https://example.com",
  "search": "blog",
  "includeSubdomains": true,
  "limit": 500
}

Só voltam URLs do host que você passou, com ou sem www. Ligue o includeSubdomains para manter também o blog.example.com. O search deixa só as URLs que contêm uma palavra, sem diferenciar maiúsculas de minúsculas. O limit corta a lista: 5.000 se você não disser, 30.000 no máximo.

Cada página aparece uma vez

Um site lista a mesma página de vários jeitos. A gente tira o que vem depois do #, os parâmetros de rastreamento utm_ e a barra no final, e ordena o resto da query. Assim cada página volta uma vez só.

truncated: true quer dizer que o site pode listar mais do que veio. Ou o limit cortou a lista, ou faltou ler o robots.txt ou um dos sitemaps até o fim. Isso acontece quando o site bloqueou a leitura, o arquivo era grande demais, veio depois dos 25 primeiros sitemaps, o tempo do mapa acabou ou o nosso proxy falhou. Quando a falha é nossa, você recebe as URLs encontradas até ali, e o mapa não custa nada.

Da URL para a página

Mapear e depois ler
import { Scrapa } from "@scrapa/sdk";

const scrapa = new Scrapa(process.env.SCRAPA_API_KEY!);

const { urls } = await scrapa.map({ url: "https://example.com", search: "blog" });
const pages = await Promise.all(
  urls.slice(0, 3).map(({ url }) => scrapa.scrape({ url })),
);

Um mapa entrega endereços, não conteúdo. Leia as páginas que você precisa com o scrape, ou mande a lista inteira para um lote.

Quanto custa

2 créditos por mapa, ache o que achar. O tráfego pelo pool gerenciado é cobrado a partir do segundo megabyte, somando todos os arquivos que o mapa leu.

Site que não lista nada é cobrado, porque respondeu. Site que bloqueou todos os arquivos não custa nada, e nem qualquer falha nossa. Para ver o preço sem fazer a chamada, use POST /v1/map/quote.

A forma para o terminal

GET /v1/map
curl "https://api.scrapa.app/v1/map?url=https://example.com&search=blog&sitemap=only" \
  -H "authorization: Bearer sc_live_your_key"

A mesma operação em GET, para quando o corpo JSON atrapalha. O bloco de proxy se abre em parâmetros de query. No SDK o método é map(), e no MCP a ferramenta é map_site.