Saltar al contenido
Herramienta básica1 credit

extract_links

Descubra y extraiga todos los enlaces de una página web. Ideal para la generación de mapas de sitio, el análisis de enlaces y los flujos de trabajo de rastreo.

Casos de uso

Generación de mapas de sitio

Cree mapas de sitio completos extrayendo todos los enlaces internos

Descubrimiento de enlaces para rastreo

Encuentre todas las URLs que visitar en un flujo de trabajo de rastreo web

Análisis de enlaces internos

Analice la estructura de enlaces internos para optimizar el SEO

Detección de enlaces rotos

Encuentre y valide todos los enlaces de una página

Endpoint

POST/api/v1/tools/extract_links
Auth Required
1 req/s en el plan Free
1 credit

Parameters

NameTypeRequiredDefaultDescription
url
stringOptional-
Página que se descargará para extraer los enlaces. Se requiere `url` o `html`.
Example: https://example.com
html
stringOptional-
HTML sin procesar que se analizará en lugar de descargar. Combínelo con `base_url` para que los href relativos se resuelvan.
Example: <a href='/about'>About</a>
base_url
stringOptional-
Base para resolver enlaces relativos; tiene prioridad sobre el `<base href>` de la propia página. Al descargar, se usa el `<base href>` de la página y, si no hay, `url`; indícala al pasar `html`.
Example: https://example.com
include_internal
booleanOptionaltrue
Incluye los enlaces que apuntan al mismo host.
Example: true
include_external
booleanOptionaltrue
Incluye los enlaces que apuntan a otros hosts. Póngalo en false para conservar solo los internos.
Example: true
filter_external
booleanOptionalfalse
El nombre que usa la herramienta MCP para pedir solo enlaces salientes: `true` equivale a `include_internal: false` y tiene prioridad sobre él. Es un alias, aceptado para que el mismo cuerpo de solicitud funcione en ambas superficies. No elimina los enlaces de tipo `other`, `anchor` o `relative`.
Example: true
filter_domains
arrayOptional-
Conserva solo los enlaces cuyo host coincida con uno de estos dominios.
Example: ["docs.example.com"]
include_anchors
booleanOptionalfalse
Incluye los enlaces que son solo un fragmento, como `#section`.
Example: false
deduplicate
booleanOptionaltrue
Colapsa las URL repetidas en una sola entrada, comparándolas sin fragmento ni barra final (`/a`, `/a/` y `/a#x` son un mismo enlace); se conserva la primera aparición.
Example: true
include_metadata
booleanOptionaltrue
Incluye el atributo `title` de cada enlace y el mapa de recuento `domains`. Cada registro de enlace lleva `href`, `text`, `type`, `domain`, `rel` y `original_href` en cualquier caso: la misma forma que devuelve la herramienta MCP.
Example: true
respect_robots
booleanOptionaltrue
Respeta el robots.txt del sitio de destino. Con el valor `true`, una ruta que robots.txt no permita a `CrawlForge` se rechaza con un 403 antes de descargar nada y no se cobran credits. Póngalo en `false` solo para destinos con los que tenga su propio acuerdo: la respuesta incluye entonces una entrada `warnings` y la anulación queda registrada en su API key.
Example: true
escalate
booleanOptionalfalse
Activa un único reintento automático a través del navegador stealth cuando la descarga simple de `url` encuentra un muro en lugar de la página: una página de desafío de Cloudflare, Amazon, DataDome, PerimeterX, Akamai o Vercel, un 403, 429 o 444 sin más, o un armazón vacío o una página de error servidos con un 2xx. La descarga simple siempre se ejecuta primero; un 404, un 5xx, un binario como un PDF o un host cuya ventana de `Retry-After` sigue abierta nunca escalan, y la entrada `html` nunca se descarga. Los enlaces se leen del HTML renderizado, de modo que la respuesta tiene la misma forma, más `escalated` (siempre que se indique este parámetro) y `stealth: { engine, vendor_detected }` cuando el renderizado se ejecutó. La escalada reutiliza la misma ruta stealth que [stealth_mode](/docs/api-reference/tools/stealth-mode) y la misma comprobación de robots.txt, y no añade ningún tratamiento nuevo de una defensa antibots; un muro en el que también se rechaza el renderizado sigue devolviéndose como página bloqueada con `escalated: true`, sin coste. Añade 5 credits, cobrados solo cuando el renderizado se ejecuta de verdad.
Example: true
escalate_engine
stringOptionalplaywright
Motor de navegador para la etapa de escalada: "playwright" (por defecto) o "camoufox" (basado en Firefox, con mayor resistencia a la detección; disponible solo donde esté instalado en el backend). Se ignora salvo que `escalate` sea `true` y la descarga simple haya quedado bloqueada.
Example: camoufox
max_inline_chars
numberOptional40000
Tamaño máximo del resultado que se devuelve en línea, en caracteres de su JSON (de 1.000 a 10.000.000). Por encima, la respuesta incluye `preview` (los primeros `max_inline_chars` caracteres del JSON formateado), `result_handle`, `total_chars`, `truncated: true` y `expires_at`, y [read_result](/docs/api-reference/tools/read-result) lee el resto por 1 credit por llamada. Los resultados almacenados se conservan 1 hora.
Example: 40000

Descarga de una URL

  • La página se descarga una vez con un tiempo de espera de 15 segundos. Un 429 o 503 cuyo Retry-After sea de 10 segundos o menos se espera y se vuelve a descargar una vez; un Retry-After más largo o ausente no se reintenta.
  • Se leen HTML, XHTML, XML y cualquier tipo text/*, y una respuesta sin Content-Type se lee como HTML. Un PDF, una imagen u otro binario devuelve 415 UNSUPPORTED_CONTENT_TYPE con next_step: "process_document" y no cobra nada: léelo con process_document.
  • Un cuerpo JSON (application/json o *+json) no devuelve enlaces, con el aviso the target returned application/json; it has no HTML links.
  • Una página que se renderiza en el cliente —menos de 200 caracteres de texto visible y un <div id="root">, "app" o "__next" vacío, o un texto que dice que la página necesita JavaScript ("Enable JavaScript…")— se devuelve con éxito, con rendered: false en data y el aviso page renders client-side; use scrape en warnings cuando no se ejecutó ningún renderizado stealth, para que un armazón vacío no se confunda con una página corta. La entrada html se comprueba igual.
  • Una llamada cuesta 1 credit. Con escalate: true la proyección es el máximo de 6 credits; los 5 credits de la etapa de escalada solo se cobran cuando la descarga simple quedó bloqueada y la etapa se ejecutó de verdad. Ningún fallo se cobra.

Ejemplos de solicitud

cURL - Extraer todos los enlaces

terminalBash
curl -X POST https://crawlforge.dev/api/v1/tools/extract_links \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "include_internal": true,
    "include_external": false,
    "deduplicate": true
  }'

TypeScript - Solo enlaces internos

extractLinks.tsTypescript
// npm install crawlforge-sdk
import { CrawlForge } from 'crawlforge-sdk';

const client = new CrawlForge({ apiKey: process.env.CRAWLFORGE_API_KEY });

const result = await client.extractLinks({
  url: 'https://example.com',
  // Internal-only: keep include_internal, switch include_external off.
  include_internal: true,
  include_external: false,
  deduplicate: true,
});

// result.data is untyped in crawlforge-sdk 0.1 — its shape is the Response Example below.
const { base_url, extracted_from, links } = result.data as {
  base_url: string; extracted_from: string; links: unknown[];
};
console.log('Base URL:', base_url);
console.log('Extracted from:', extracted_from);

for (const link of links) console.log(link);

// Narrow to specific hosts instead of a blanket internal/external split.
const docsOnly = await client.extractLinks({
  url: 'https://example.com',
  filter_domains: ['docs.example.com'],
});

Ejemplo de respuesta

200 OK210ms
{
"success": true,
"data": {
"links": [
{
"href": "https://example.com/about",
"text": "About",
"type": "internal",
"domain": "example.com",
"rel": null,
"original_href": "/about",
"title": "About us"
},
{
"href": "https://example.com/products",
"text": "Products",
"type": "internal",
"domain": "example.com",
"rel": null,
"original_href": "/products"
},
{
"href": "https://other-site.com/",
"text": "External Resource",
"type": "external",
"domain": "other-site.com",
"rel": "nofollow",
"original_href": "https://other-site.com"
},
{
"href": "mailto:hello@example.com",
"text": "Email us",
"type": "other",
"domain": null,
"rel": null,
"original_href": "mailto:hello@example.com"
}
],
"statistics": {
"total_links": 4,
"internal_links": 2,
"external_links": 1,
"anchor_links": 0,
"relative_links": 0,
"other_links": 1,
"unique_domains": 2
},
"domains": {
"example.com": 2,
"other-site.com": 1
},
"base_url": "https://example.com",
"extracted_from": "https://example.com/"
},
"credits_used": 1,
"credits_remaining": 999,
"processing_time": 210
}
Field Descriptions
data.linksCada enlace como { href, text, type, domain, rel, original_href } (+ title si include_metadata está activo): la misma forma de registro que devuelve la herramienta MCP
data.links[].typeinternal (mismo host que la página), external, anchor (#fragmento, con include_anchors), other (mailto:, tel:, javascript: y otros esquemas no web; href es null salvo en mailto: y tel:) o relative (entrada html sin base_url)
data.links[].original_hrefEl href tal como aparece en la página; href es la URL absoluta resuelta
data.statisticsRecuentos por tipo: total_links, internal_links, external_links, anchor_links, relative_links, other_links, unique_domains
data.domainsEnlaces por dominio (solo con include_metadata)

Manejo de errores

Bloqueado por un muro antibots (403, 444 o 502)

El destino respondió con una página de desafío antibots en lugar del contenido, sea cual sea su código HTTP. La respuesta es success: false con error.code BLOCKED, un objeto blocked que nombra el vendor (por ejemplo cloudflare o akamai) y la evidence por la que se reconoció, y un next_step: extract_links with escalate:true, or stealth_mode operation:"scrape". El código es el propio del destino cuando es 403, 404, 410, 429, 444 o 451, y 502 en cualquier otro caso, incluido un muro servido con 200. No se cobra ningún credit. Con escalate: true el muro se renderiza una vez en el navegador stealth; si el renderizado también se rechaza, el mismo error lleva escalated: true y ningún next_step.

El destino respondió con un error (502 Bad Gateway)

El destino respondió con un error HTTP y sin un muro antibots reconocido. error.code es UPSTREAM_HTTP y el mensaje es Target answered HTTP <n>. Un 403, 404, 410, 429, 444 o 451 se devuelve tal cual como código de la respuesta; cualquier otro error (un 5xx, o un 400 o 401 del propio destino) es un 502, para que no se confunda con un problema de su solicitud o de su API key. Un 403, 429 o 444 incluye además next_step. No se cobra ningún credit.

Bloqueado por robots.txt (403 Forbidden)

El robots.txt del sitio de destino no permite esta ruta a CrawlForge. Establezca respect_robots: false para anularlo si tiene su propio acuerdo con el destino: la anulación queda registrada en su API key. La anulación no alcanza a un host incluido en la lista de exclusión permanente de CrawlForge, que se rechaza sea cual sea el valor de respect_robots.

Tipo de contenido no admitido (415 Unsupported Media Type)

El destino sirvió un PDF, una imagen u otro binario. error.code es UNSUPPORTED_CONTENT_TYPE, el mensaje es Unsupported content type <type>: extract_links reads HTML y next_step es process_document. El cuerpo no se lee, no se escala nada y no se cobra ningún credit.

Backend de escalada no configurado (503 TOOL_NOT_AVAILABLE)

escalate: true ejecuta su etapa stealth en el backend de ejecución de CrawlForge. Cuando ese backend no está configurado, la etapa devuelve 503 y no se cobra ningún credit.

Herramientas relacionadas