lintlab SEO Site QA

Ferramenta MCP (via servidor MCP da Apify) que rastreia um site público ou seu sitemap XML e retorna links internos quebrados e problemas técnicos de SEO por página: títulos duplicados, meta descrições ausentes, problemas de canonical e headings, cada um com uma correção sugerida. Apenas HTTP, sem renderização de JavaScript. Pague por página verificada na Apify.

Servidor MCP hospedado

npx add-mcp 'https://mcp.apify.com?tools=lintlab/seo-site-qa'

Instala no Claude Code, Codex, Cursor e outros

Documentação

Verificador de Links Quebrados e Auditoria Técnica de SEO (lintlab/seo-site-qa) Actor

Verificador de links quebrados e auditoria técnica de SEO para sites públicos: encontre links internos quebrados, títulos duplicados, meta descrições ausentes, problemas de canonical, headings, robots e hreflang. Rastreie a partir de uma URL ou sitemap XML para correções por página e um resumo do site. Crawler de SEO somente HTTP, sem JavaScript.

  • URL: https://apify.com/lintlab/seo-site-qa.md
  • Desenvolvido por: lintlab (comunidade)
  • Categorias: Ferramentas de SEO, Ferramentas para desenvolvedores
  • Estatísticas: 2 usuários no total, 1 usuário mensal, 100,0% de execuções bem-sucedidas, 0 favoritos
  • Avaliação dos usuários: Sem avaliações ainda

Preços

a partir de $3,20 / 1.000 páginas auditadas

Este Actor é pago por evento. Você não é cobrado pelo uso da plataforma Apify, mas apenas por um preço fixo para eventos específicos. Como este Actor oferece suporte a descontos da Apify Store, o preço fica mais baixo quanto maior for o seu plano de assinatura.

Saiba mais: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

O que é um Apify Actor?

Um Actor é um programa de nuvem serverless que roda na plataforma Apify. Ele tem dois modos de execução. No modo Batch, um Actor aceita uma entrada JSON bem definida, executa uma ação que pode levar de alguns segundos a algumas horas, e opcionalmente produz uma saída JSON bem definida, datasets com resultados ou arquivos em key-value store. No modo Standby, um Actor fornece um servidor web que pode ser usado como site, API ou servidor MCP.

O vocabulário da Apify e o modelo da plataforma são definidos uma vez, no quickstart para agentes em https://apify.com/agents.md.

Como integrar um Actor?

Se perguntado sobre integração, você ajuda desenvolvedores a integrar Actors em seus projetos. Você se adapta à stack deles e entrega integrações seguras, bem documentadas e prontas para produção.

Não adivinhe um caminho de integração. Cada um deles está no quickstart para agentes em https://apify.com/agents.md: o servidor MCP da Apify, Agent Skills com a CLI da Apify, os clientes JavaScript e Python, a API REST e o caminho sem conta para um agente sem humano para fazer login. Ele também traz a regra sobre informar o custo antes da primeira execução paga.

Para exemplos já conectados ao schema de entrada deste próprio Actor, consulte a seção API abaixo.

Cada biblioteca de cliente tem documentação de referência que o quickstart não repete: JavaScript/TypeScript (npm install apify-client) e Python (pip install apify-client).

README

Verificador de Links Quebrados e Auditoria Técnica de SEO

Encontre links internos quebrados e problemas técnicos de SEO em um site público. Comece a partir de uma URL do site ou de um sitemap XML e obtenha descobertas em nível de página para links, títulos, meta descrições, canonicals, headings e muito mais, além de um resumo do site com correções sugeridas. É uma auditoria baseada em HTTP e não renderiza JavaScript.

Broken link & SEO check output: Crawlee Blog page has an H1 error, title warning, and structured data notice.

Saída real de uma execução de 10 páginas em crawlee.dev (2026-10-01): o registro da página do blog e suas três descobertas; todos os 10 registros totalizam 1 erro, 11 avisos e 9 notificações.

O que ele verifica

  • Títulos, meta descrições, headings, canonicals, diretivas de robots, hreflang, imagens e dados estruturados
  • Títulos e descrições duplicados no site auditado
  • Links internos quebrados e todos os links internos com redirecionamento (status, URL final, saltos), com verificações HEAD em cache e fallback GET; verificações com limite de taxa são relatadas como não verificadas, nunca como quebradas
  • Índices de sitemap comuns, compactados com gzip e aninhados
  • $0,004 por página buscada e salva com sucesso

Este Actor é somente HTTP e não renderiza JavaScript.

Início rápido

{"startUrls":[{"url":"https://example.com"}],"discoverSitemap":true,"maxPages":100,"checkLinks":true}

Experimente um exemplo pronto: Verificador de links quebrados. Abra-o, clique em Iniciar, depois copie e substitua pelo seu próprio site.

Uso com agentes de IA / MCP

Chame lintlab/seo-site-qa por meio da API da Apify ou do servidor MCP da Apify. Use o findings por página para correções precisas e SUMMARY ou SUMMARY.md para um plano em nível de site.

Visão geral

SEO Site QA é uma auditoria técnica de SEO somente HTTP para sites que você possui ou está autorizado a auditar. Ele aceita páginas, um sitemap XML ou um índice de sitemap; verifica cada página permitida; e grava JSON compacto e determinístico além de um resumo do site. É destinado a desenvolvedores, agências, fluxos de CI e agentes de IA que precisam de descobertas acionáveis sem executar um navegador.

O que ele faz

  • Lê sitemaps comuns e compactados com gzip, incluindo índices de sitemap aninhados.
  • Opcionalmente, descobre um sitemap a partir de robots.txt e depois /sitemap.xml quando recebe apenas uma homepage.
  • Usa o CheerioCrawler do Crawlee com requisições HTTP protegidas. Ele não inicia um navegador.
  • Audita até 5.000 páginas e pode opcionalmente descobrir mais páginas a partir de links internos.
  • Verifica links internos com requisições HEAD em cache e fallback GET, dentro de um limite configurável.
  • Produz um item de dataset por página tentada, SUMMARY JSON e SUMMARY.md.
  • Cobra apenas após uma página permitida e buscada com sucesso ter sido salva no dataset.

Entrada

{
  "startUrls": [{ "url": "https://crawlee.dev" }],
  "discoverSitemap": true,
  "maxPages": 100,
  "sameHostOnly": true,
  "followLinks": false,
  "checkLinks": true,
  "maxLinkChecks": 500,
  "timeoutSecs": 20,
  "concurrency": 5
}

Você pode usar sitemapUrl em vez de, ou junto com, startUrls. startUrls também aceita strings de URL simples pelo caminho de entrada programática. A concorrência global padrão é 5; requisições para uma mesma origem são limitadas a 2 simultâneas.

Saída por página

Cada item do dataset descreve uma página tentada. Páginas bloqueadas e com falha incluem um error e não são cobradas.

{
  "url": "https://example.com/about",
  "finalUrl": "https://example.com/about",
  "status": 200,
  "redirectChain": [],
  "title": "About Example Company",
  "metaDescription": "How our team builds useful products.",
  "h1": ["About us"],
  "canonical": "https://example.com/about",
  "indexable": true,
  "wordCount": 438,
  "jsonLdTypes": ["AboutPage"],
  "findings": [
    {
      "checkId": "opengraph.image_missing",
      "severity": "notice",
      "message": "Open Graph image is missing.",
      "fix": "Add a og:image meta tag for richer social previews."
    }
  ],
  "counts": { "error": 0, "warning": 0, "notice": 1 },
  "checkedAt": "2026-01-01T00:00:00.000Z"
}

redirectChain contém objetos {url, status, location}. Uma descoberta sempre contém checkId, severity, message e fix; value é incluído quando útil.

Verificações

Os IDs de verificação são valores de API estáveis. Novas verificações podem ser adicionadas em versões futuras.

ID da verificaçãoSeveridadeCondição
title.missingerroSem elemento <title>
title.emptyerroO elemento de título não tem texto
title.too_longavisoO título tem mais de 60 caracteres
title.too_shortavisoO título tem menos de 10 caracteres
title.duplicateavisoO mesmo título não vazio aparece em várias páginas auditadas
description.missingavisoA meta descrição está ausente ou vazia
description.too_longavisoA meta descrição tem mais de 160 caracteres
description.duplicateavisoA mesma descrição não vazia aparece em várias páginas auditadas
h1.missingerroSem heading H1
h1.multipleavisoMais de um H1
headings.level_skipavisoA ordem dos headings pula mais de um nível
canonical.missingavisoO link canonical está ausente ou vazio
canonical.relativeavisoO canonical não está escrito como URL absoluta
canonical.elsewhereavisoO canonical resolve para uma URL diferente
canonical.malformederroO canonical não pode ser analisado como URL
canonical.non_200erroO destino do canonical não retorna HTTP 200 ou não pode ser buscado
robots.meta_noindexavisoMeta robots contém noindex
robots.meta_nofollowavisoMeta robots contém nofollow
robots.x_noindexavisoX-Robots-Tag contém noindex
robots.x_nofollowavisoX-Robots-Tag contém nofollow
robots.blocked_sitemaperroA URL está em um sitemap, mas é desautorizada pelo robots.txt
robots.disallowederroURL inicial/descoberta fora do sitemap é desautorizada
http.non_200erroA resposta final da página está fora de 2xx
sitemap.redirectedavisoUma URL retirada do sitemap redireciona
html.lang_missingaviso<html> não tem lang
html.lang_malformedavisolang não é uma tag BCP 47 válida
viewport.missingavisoA meta tag de viewport está ausente
images.alt_missingavisoUma ou mais imagens não têm atributo alt; o valor tem contagem e as cinco primeiras fontes
opengraph.title_missingnotificaçãoog:title está ausente ou vazio
opengraph.description_missingnotificaçãoog:description está ausente ou vazio
opengraph.image_missingnotificaçãoog:image está ausente ou vazio
jsonld.invaliderroUm bloco JSON-LD não é analisado como JSON
jsonld.typesnotificaçãoTipos JSON-LD válidos foram encontrados; os tipos são relatados em value e jsonLdTypes
resources.mixed_contenterroUma página HTTPS referencia um recurso http://
html.too_largeavisoHTML não compactado tem mais de 1,5 MB
hreflang.malformedavisoO idioma do hreflang ou o destino HTTP(S) absoluto está malformado
links.broken_internalerroO link interno retorna 4xx diferente de 429, ou 5xx diferente de 503 com Retry-After, ou tem erro de rede
links.rate_limitednotificaçãoHTTP 429 ou HTTP 503 com Retry-After persistiu após duas tentativas, então o link não foi verificado; o valor contém target, status e retryAfter
links.redirectednotificação para 301/308; aviso para 302/303/307O link interno tem um salto de redirecionamento; o valor contém url, status e location do primeiro salto, finalUrl e hops
links.redirect_chainavisoO link interno tem mais de um salto de redirecionamento
fetch.failederroA busca da página falha antes que uma resposta HTTP esteja disponível

Um conjunto JSON-LD vazio não é um erro. Se existir JSON-LD válido, seus valores @type são relatados. As descobertas de links são anexadas a cada página de origem; uma cadeia de redirecionamento produz links.redirect_chain em vez de links.redirected. O resumo lista links quebrados e links com redirecionamento.

Resumo e pontuação

O key-value store padrão recebe:

  • SUMMARY: JSON com páginas auditadas/tentadas, contagens agregadas, principais problemas, grupos de títulos e descrições duplicados, brokenLinks, redirectedLinks, redirectedLinksTruncated, erros de sitemap e a pontuação. redirectedLinks contém {from, url, status, finalUrl, hops} para até 500 URLs de links únicos; status é o primeiro status de redirecionamento e from é uma página de origem.
  • rateLimitedLinks: número de descobertas links.rate_limited em SUMMARY.
  • SUMMARY.md: os mesmos resultados principais em um relatório Markdown legível.

A pontuação é:

100 - min(100, (errors × 5 + warnings × 2 + notices × 0.25) / successful pages)

Ela é limitada a 0–100 e arredondada para uma casa decimal. A fórmula é deliberadamente simples e comparativa; um problema crítico para o negócio pode importar mais do que seu peso numérico.

Preços

O evento page-audited custa $0,004 por página auditada com sucesso, ou $4 por 1.000 páginas. As verificações de links internos são gratuitas e limitadas por maxLinkChecks. Páginas desautorizadas, falhas de rede e respostas finais de página fora de 2xx são gravadas para diagnóstico, mas não são cobradas. O Actor para de gravar mais resultados de página quando a plataforma informa que o limite de cobrança do evento foi atingido.

Limites e comportamento

  • Máximo de 5.000 páginas agendadas por execução e 10.000 verificações de links internos únicos.
  • Máximo de 10 redirecionamentos por operação HTTP.
  • Respostas HTML limitadas a 10 MB; respostas de sitemap a 20 MB.
  • Índices de sitemap limitados a 100 documentos de sitemap buscados por execução.
  • As verificações de links usam HEAD, com fallback para GET em HTTP 405 ou 501. Os destinos canônicos são verificados separadamente e armazenados em cache.
  • As verificações de links param após os cabeçalhos da resposta; HTTP 429 e 503 com Retry-After recebem no máximo duas tentativas, após as quais são relatados como não verificados.
  • sameHostOnly compara nomes de host. Fragmentos de URL são removidos durante a normalização.
  • O crawler avalia apenas HTML entregue pelo servidor. Ele não executa JavaScript, mede layout renderizado nem executa Core Web Vitals.
  • A validação de hreflang verifica a sintaxe do idioma e destinos HTTP(S) absolutos; ela não verifica anotações recíprocas.
  • A correspondência de duplicados é insensível a maiúsculas/minúsculas após remover espaços, não semântica.
  • As regras de robots.txt suportam grupos de user-agent, Allow/Disallow, * e $ terminal; diretivas não padronizadas incomuns são ignoradas.

Segurança e conformidade

Use este Actor apenas para sites que você possui ou tem permissão para auditar.

  • O user agent começa com lintlab-seo-qa/1.0; token de produto robots: lintlab-seo-qa.
  • robots.txt é armazenado em cache por origem. Erros de fetch/rede e respostas 5xx falham de forma fechada (todas as URLs dessa origem são desautorizadas); respostas 4xx permitem rastreamento conforme o comportamento do RFC 9309.
  • Cada página, sitemap, canônico, verificação de link e salto de redirecionamento é restrito a HTTP(S), resolvido por DNS antes da conexão, e bloqueado se qualquer resultado for espaço privado, loopback, link-local, CGNAT, multicast, reservado, não especificado ou ULA IPv6/espaço privado mapeado por IPv4.
  • Redirecionamentos são seguidos manualmente, no máximo 10 saltos, para que cada destino receba a mesma validação de SSRF.
  • Nenhum proxy, entrada de login/cookie, tratamento de CAPTCHA, navegador ou comportamento furtivo é utilizado.
  • A saída não extrai e-mails, números de telefone ou nomes pessoais.

Desenvolvimento local

Requer Node.js 20 ou mais recente.

npm ci
npm test
APIFY_LOCAL_STORAGE_DIR=./storage CRAWLEE_STORAGE_DIR=./storage node src/main.js

Antes do comando final, escreva a entrada desejada do Actor em storage/key_value_stores/default/INPUT.json (ou use apify run --purge com a CLI do Apify).

Mais ferramentas lintlab


Construído pela lintlab — ferramentas de dados pequenas e confiáveis. Testado antes do lançamento. Suporte: abra uma issue na aba Issues deste Actor aqui no Apify.

Esquema de entrada do Actor

startUrls (tipo: array):

Páginas a auditar. Com uma homepage e descoberta de sitemap habilitada, o Actor também verifica robots.txt e /sitemap.xml.

sitemapUrl (tipo: string):

URL opcional de sitemap XML ou índice de sitemap. Sitemaps compactados com gzip são suportados.

discoverSitemap (tipo: boolean):

Quando a única URL inicial é uma homepage, tente diretivas de Sitemap em robots.txt e depois /sitemap.xml.

maxPages (tipo: integer):

Número máximo de páginas únicas agendadas para auditoria.

sameHostOnly (tipo: boolean):

Ignore entradas de sitemap e links seguidos em outros hostnames.

followLinks (tipo: boolean):

Adicione links internos encontrados nas páginas auditadas à fila de auditoria, limitado pelo máximo de páginas.

checkLinks (tipo: boolean):

Verifique alvos de links internos com HEAD e um fallback GET. Verificações de link não são cobradas.

maxLinkChecks (tipo: integer):

Máximo de alvos únicos de links internos verificados durante a execução.

timeoutSecs (tipo: integer):

Tempo limite aplicado a cada requisição HTTP.

concurrency (tipo: integer):

Máximo de tarefas de página simultâneas. Requisições a qualquer host são limitadas a duas por vez.

Exemplo de objeto de entrada do Actor

{
  "startUrls": [
    {
      "url": "https://crawlee.dev"
    }
  ],
  "discoverSitemap": true,
  "maxPages": 100,
  "sameHostOnly": true,
  "followLinks": false,
  "checkLinks": true,
  "maxLinkChecks": 500,
  "timeoutSecs": 20,
  "concurrency": 5
}

Esquema de saída do Actor

pages (tipo: string):

Sem descrição

summary (tipo: string):

Inclui rateLimitedLinks, o número de descobertas links.rate_limited.

summaryMarkdown (tipo: string):

Sem descrição

API

Você pode executar este Actor programaticamente usando nossa API. Abaixo estão exemplos de código em JavaScript, Python e CLI, bem como a especificação OpenAPI e a configuração do servidor MCP.

Exemplo em JavaScript

import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://crawlee.dev"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lintlab/seo-site-qa").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

Exemplo em Python

from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": [{ "url": "https://crawlee.dev" }] }

# Run the Actor and wait for it to finish
run = client.actor("lintlab/seo-site-qa").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

Exemplo em CLI

echo '{
  "startUrls": [
    {
      "url": "https://crawlee.dev"
    }
  ]
}' |
apify call lintlab/seo-site-qa --silent --output-dataset

Configuração do servidor MCP

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lintlab/seo-site-qa"
        }
    }
}

O servidor hospedado faz login com OAuth na primeira conexão, então nenhum token de API pertence a esta configuração. Clientes sem suporte a OAuth podem enviar um cabeçalho Authorization: Bearer <APIFY_API_TOKEN> em vez disso, usando um token de API & Integrações no Console do Apify (https://console.apify.com/settings/integrations).

Especificação OpenAPI

Baixe a definição OpenAPI: https://api.apify.com/v2/actors/SwggFLZIVFbAwipoj/builds/UblUFT9X56veK3F5y/openapi.json