Link Extraction API
Fetches a live public page and lists every link on it: the target URL, anchor text, rel values (nofollow, sponsored, ugc), whether it is internal, and how often it appears. One page per GET, or up to 600 pages in a job.
Need the page's text or metadata too? Use Scrape with include=links,metadata.
https://rankfield.dev/v1/html/link-extraction?url={url}Send Authorization: Bearer YOUR_API_KEY. Get a free key; no account needed.
Parameters#
| Name | Type | Description |
|---|---|---|
url | string | A public https:// page. http:// is upgraded and a missing scheme gets https://. Credentials, custom ports and private hosts are refused. |
view | string | unique: one entry per target, with occurrences. occurrences: one entry per link, in page order. |
type | string | all, internal (same hostname as the final URL) or external. counts always cover the whole page. |
maxAge | integer | Seconds, 0 to 3,600. A copy collected at most this long ago may be reused (cached: true); 0 always fetches. |
wait | integer | Seconds to wait for the page, 1 to 85. Not ready by then: 202 with resultsUrl, where the answer arrives. |
Response#
| Field | Type | Description |
|---|---|---|
url finalUrl status redirects | string, integer, array | What you asked, the page that answered after redirects, its HTTP status and each redirect. |
title | string | null | The page's <title>. |
collectedAt cached | string, boolean | When the page was fetched, and whether this copy was reused (see maxAge). |
counts | object | links (distinct targets), internal, external, occurrences (every link). |
links | array | href, anchor, internal, rel, nofollow, sponsored, ugc, occurrences. |
view jobId | string | The view used, and the job that fetched the page. |
Errors#
Errors come as {"error":{"message":"…"}} with the HTTP status.
| Status | When |
|---|---|
202 | Still running after wait seconds. Read the answer at resultsUrl. |
400 | The URL or a parameter is not valid, e.g. {"error":{"message":"Expected a public https:// page URL in ?url="}}. |
401 | The key is missing, unknown or revoked. |
409 | A jsonl or csv download of a job that has not finished. |
413 | More than 600 URLs in one job. |
422 | The website answered with an error, timed out or sent something that is not HTML. The body has the page's status and error with message, code (such as SOURCE_HTTP_404) and retryable. |
429 | Busy right now: our capacity is full, or the website is being paced. Retry after Retry-After. |
503 | The service is busy or briefly unavailable. Retry after Retry-After. |
Price and limits#
- Free; no per-call charge.
- No per-key limits. A job holds up to 600 URLs; more is a
413. A single-page GET is a one-URL job.
Up to 600 pages in one job#
POST /v1/html/link-extraction/jobs with {"urls":[…]} (1 to 600 URLs), view, delivery (standard, the default, or priority), maxAge, and an optional Idempotency-Key header: the same key and body return the same job instead of a new one. The answer is 202 with statusUrl, resultsUrl and deadlineAt.
The deadline is fixed per job, whatever its size: priority 90 seconds, standard 330 seconds (deadlineAt in the answer). By then every page is answered, as a result or as failed. Pages from one website are fetched at up to 5 a second, so about 400 pages of one site fit a priority job and about 1,500 a standard one; a job spread over many sites fits easily. For many pages of one site, use standard.
GET /v1/html/link-extraction/jobs/{id}/results returns pages as each one finishes, with position (its index in your list). Pass nextCursor back as cursor until it is null. Add wait (0 to 25 seconds) to hold the request until the next page is ready. A finished job also streams as ?format=jsonl or ?format=csv. Jobs are kept for 24 hours.
Reference: https://rankfield.dev/docs/get-started/batch-jobs
curl -X POST "https://rankfield.dev/v1/html/link-extraction/jobs" \
-H "Authorization: Bearer $RANKFIELD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crawl-2026-10-25" \
-d '{"urls":["https://example.com/","https://example.com/about"]}'import os
import requests
response = requests.post(
"https://rankfield.dev/v1/html/link-extraction/jobs",
headers={"Authorization": f"Bearer {os.environ['RANKFIELD_API_KEY']}", "Content-Type": "application/json", "Idempotency-Key": "crawl-2026-10-25"},
json={"urls": ["https://example.com/", "https://example.com/about"]},
)
print(response.json())const response = await fetch("https://rankfield.dev/v1/html/link-extraction/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RANKFIELD_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "crawl-2026-10-25",
},
body: JSON.stringify({"urls":["https://example.com/","https://example.com/about"]}),
});
console.log(await response.json());Notes#
- CSV rows, one per link:
page_url, page_status, final_url, href, anchor, internal, rel, nofollow, sponsored, ugc, occurrences, error.
See also#
- Full reference: https://rankfield.dev/docs/link-extraction/extract-links
- MCP tools on
https://rankfield.dev/mcp:extract_page_links,start_link_extraction_job,get_link_extraction_results - Try it with your key: the API playground
- This page as Markdown: /endpoints/html-links.md