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.
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.txte depois/sitemap.xmlquando recebe apenas uma homepage. - Usa o
CheerioCrawlerdo 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,
SUMMARYJSON eSUMMARY.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ção | Severidade | Condição |
|---|---|---|
title.missing | erro | Sem elemento <title> |
title.empty | erro | O elemento de título não tem texto |
title.too_long | aviso | O título tem mais de 60 caracteres |
title.too_short | aviso | O título tem menos de 10 caracteres |
title.duplicate | aviso | O mesmo título não vazio aparece em várias páginas auditadas |
description.missing | aviso | A meta descrição está ausente ou vazia |
description.too_long | aviso | A meta descrição tem mais de 160 caracteres |
description.duplicate | aviso | A mesma descrição não vazia aparece em várias páginas auditadas |
h1.missing | erro | Sem heading H1 |
h1.multiple | aviso | Mais de um H1 |
headings.level_skip | aviso | A ordem dos headings pula mais de um nível |
canonical.missing | aviso | O link canonical está ausente ou vazio |
canonical.relative | aviso | O canonical não está escrito como URL absoluta |
canonical.elsewhere | aviso | O canonical resolve para uma URL diferente |
canonical.malformed | erro | O canonical não pode ser analisado como URL |
canonical.non_200 | erro | O destino do canonical não retorna HTTP 200 ou não pode ser buscado |
robots.meta_noindex | aviso | Meta robots contém noindex |
robots.meta_nofollow | aviso | Meta robots contém nofollow |
robots.x_noindex | aviso | X-Robots-Tag contém noindex |
robots.x_nofollow | aviso | X-Robots-Tag contém nofollow |
robots.blocked_sitemap | erro | A URL está em um sitemap, mas é desautorizada pelo robots.txt |
robots.disallowed | erro | URL inicial/descoberta fora do sitemap é desautorizada |
http.non_200 | erro | A resposta final da página está fora de 2xx |
sitemap.redirected | aviso | Uma URL retirada do sitemap redireciona |
html.lang_missing | aviso | <html> não tem lang |
html.lang_malformed | aviso | lang não é uma tag BCP 47 válida |
viewport.missing | aviso | A meta tag de viewport está ausente |
images.alt_missing | aviso | Uma ou mais imagens não têm atributo alt; o valor tem contagem e as cinco primeiras fontes |
opengraph.title_missing | notificação | og:title está ausente ou vazio |
opengraph.description_missing | notificação | og:description está ausente ou vazio |
opengraph.image_missing | notificação | og:image está ausente ou vazio |
jsonld.invalid | erro | Um bloco JSON-LD não é analisado como JSON |
jsonld.types | notificação | Tipos JSON-LD válidos foram encontrados; os tipos são relatados em value e jsonLdTypes |
resources.mixed_content | erro | Uma página HTTPS referencia um recurso http:// |
html.too_large | aviso | HTML não compactado tem mais de 1,5 MB |
hreflang.malformed | aviso | O idioma do hreflang ou o destino HTTP(S) absoluto está malformado |
links.broken_internal | erro | O link interno retorna 4xx diferente de 429, ou 5xx diferente de 503 com Retry-After, ou tem erro de rede |
links.rate_limited | notificação | HTTP 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.redirected | notificação para 301/308; aviso para 302/303/307 | O link interno tem um salto de redirecionamento; o valor contém url, status e location do primeiro salto, finalUrl e hops |
links.redirect_chain | aviso | O link interno tem mais de um salto de redirecionamento |
fetch.failed | erro | A 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.redirectedLinkscontém{from, url, status, finalUrl, hops}para até 500 URLs de links únicos;statusé o primeiro status de redirecionamento efromé uma página de origem.rateLimitedLinks: número de descobertaslinks.rate_limitedemSUMMARY.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.
sameHostOnlycompara 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.txtsuportam 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
- XML Sitemap Checker, Validator & URL Extractor: valide sitemaps e exporte cada URL
- Website Screenshot & Visual Regression Diff: capturas de tela de página inteira com diffs de pixels
- PDF to Markdown & Text Extractor: Markdown ciente de páginas para RAG e agentes de IA
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