Link Extractor - All Links from Any Page with Anchor Text avatar

Link Extractor - All Links from Any Page with Anchor Text

Pricing

from $8.00 / 1,000 page scans

Go to Apify Store
Link Extractor - All Links from Any Page with Anchor Text

Link Extractor - All Links from Any Page with Anchor Text

Extract every link from any webpage. Input: a list of page URLs. Output: JSON with the absolute link URL, anchor text, internal/external type and rel flags (nofollow, sponsored, ugc), plus mailto and tel lists. $0.01 per page flat, however many links it finds. No start fee, no browser, no code.

Pricing

from $8.00 / 1,000 page scans

Rating

0.0

(0)

Developer

Broke to Built

Broke to Built

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

10 days ago

Last modified

Share

Link Extractor - every link on a page, with anchor text and rel flags

Give it a page URL, get every <a href> on it - resolved to an absolute URL, classified internal vs external, with clean anchor text and the rel attributes that matter for SEO (nofollow, sponsored, ugc). mailto: and tel: links come back in their own lists.

One record per page, all links nested inside it, $0.01 per page scanned no matter how many links the page turns out to have. No API key, no browser, no crawl to configure.


What you get, per page

counts total, internal, external, nofollow, sponsored, ugc, mailto, tel
links[] href, text, type, rel, target, nofollow, sponsored, ugc
mailto[] href, email, text
tel[] href, tel, text
url, finalUrl, statusCode, redirected
  • Absolute URLs. A page writes /pricing; you get https://site.com/pricing. Resolution honours a <base href> element if the page has one, and otherwise resolves against the final URL after redirects - so a link list from a redirected page still points at the right host.
  • Clean anchor text. Nested tags stripped, HTML entities decoded (&amp;, &#8217;, &mdash; and ~60 named entities), whitespace collapsed. An anchor wrapping an icon and a span comes back as the words a human sees.
  • Internal vs external by hostname (see the honest limit on subdomains below).
  • rel flags parsed, not just echoed. rel="nofollow sponsored" becomes nofollow: true, sponsored: true as well as the raw string.
  • Deduplicated on href + anchor text, so a nav link repeated in the footer appears once, while the same URL linked from two different phrases appears twice - which is what a link audit wants.
  • mailto: and tel: separated out with the address and number already parsed. Fragment-only (#top), javascript:, data: and about: hrefs are dropped.

Input

{ "url": "https://apify.com/store" }

Bulk - one record and one charge per page:

{ "urls": ["https://apify.com/store", "https://en.wikipedia.org/wiki/Hyperlink"], "maxUrls": 50 }
FieldTypeDefaultNotes
urlstring-One page URL. A bare domain gets https:// prepended.
urlsarray of strings-Bulk list; takes precedence over url.
maxUrlsinteger50Hard cap on pages processed, and therefore on spend.

Output - a real record

Verbatim from a live run on 2026-08-15, links truncated to the first three of 138:

{
"url": "https://apify.com/store",
"finalUrl": "https://apify.com/store",
"statusCode": 200,
"redirected": false,
"counts": {
"total": 138, "internal": 90, "external": 48,
"nofollow": 19, "sponsored": 0, "ugc": 0, "mailto": 0, "tel": 0
},
"links": [
{ "href": "https://apify.com/", "text": "", "type": "internal", "rel": null, "target": null, "nofollow": false, "sponsored": false, "ugc": false },
{ "href": "https://console.apify.com/sign-up", "text": "Get started", "type": "external", "rel": null, "target": null, "nofollow": false, "sponsored": false, "ugc": false },
{ "href": "https://console.apify.com/sign-in", "text": "Log in", "type": "external", "rel": null, "target": null, "nofollow": false, "sponsored": false, "ugc": false }
],
"mailto": [],
"tel": []
}

Two things in that record are worth pointing at, because they will surprise you otherwise:

  • console.apify.com is typed external. Classification compares the exact hostname, so a subdomain of the same site counts as external. If you are auditing a site that spans www., blog. and app. subdomains, group by hostname yourself rather than trusting type.
  • The first link has "text": "". That is a logo anchor wrapping an image - a real, correctly reported empty anchor, and exactly the kind of thing an accessibility or SEO audit is looking for.

The same run on https://en.wikipedia.org/wiki/Hyperlink returned 436 links (288 internal, 148 external, 44 nofollow) in one record, for the same $0.01.


Call it from code or an agent

curl -X POST "https://api.apify.com/v2/acts/EliAI~webpage-links-extractor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "content-type: application/json" \
-d '{"urls":["https://example.com"],"maxUrls":50}'

Agents can call it as a tool over Apify MCP:

  • Capability: list every hyperlink on one or many pages, with anchor text and rel flags
  • Required input: url (string) or urls (array)
  • Returns: one JSON record per page; counts for a summary, links for the detail
  • Bounded: maxUrls caps the run; it does not follow links or crawl
  • Side effects: none - one GET per page

Pricing

$0.01 per page scanned - one page-scanned event per URL that returned a usable HTML response. No actor-start fee, and the price does not move with the number of links: the 138-link page and the 436-link page above each cost $0.01.

Honest comparison, measured on the store 2026-08-15. The shape of the price is the whole difference here:

ActorPrice shapeA 436-link page
eliai/webpage-links-extractor (this one)$0.01 per page, no start fee$0.01
automation-lab/link-extractor$0.035 start + per-URL event$0.035 before a single link
ninhothedev/website-link-extractor$0.00005 start + $0.0005 per dataset item$0.22 if each link is an item
codescraper/website-social-links-scraper$0.00005 start + $0.0005 per item (+$0.002 per social profile)scales the same way

Per-dataset-item pricing gets cheaper than this on pages with very few links, and more expensive as pages get link-heavy - a real site's navigation alone is often 80+ links. A flat per-page price is predictable, which is the property that matters when a script or an agent is deciding how many pages to scan.

When NOT to use this

  • Crawling a site. It does not follow links. Give it the URLs you want; to discover them, use Sitemap URL Extractor.
  • Checking whether the links work. It reports what the page links to, not what those URLs answer. For that use Broken Link Checker or Redirect Chain Checker.
  • Links injected by JavaScript. The served HTML is parsed with no browser, so anchors that a client-side framework renders after load are not there to find.
  • Treating subdomains as one site. type compares exact hostnames - see the note above.
  • Harvesting email addresses at scale. mailto: links are returned because a contact page's address is a legitimate part of a link audit; scraping addresses for unsolicited mail is not what this is for, and it is your obligation under GDPR/CAN-SPAM either way.
  • Pages behind a login or aggressive bot protection. It fetches anonymously - no cookies, no session, no proxy rotation.

FAQ

How do I get all the links on a webpage with their anchor text? Pass the URL. Every <a href> comes back as an absolute URL with clean anchor text, deduplicated, with mailto: and tel: in their own lists - one JSON record for the whole page.

Can it tell internal links from external ones? Yes, by hostname, with counts.internal and counts.external for the summary. Note that a subdomain (blog.site.com seen from site.com) is typed external - group by hostname yourself if you want registrable-domain semantics.

Does it show nofollow, sponsored and UGC links? Yes - the raw rel string plus parsed booleans per link, and totals in counts. That is what a link-equity or paid-placement audit needs.

Why do absolute URLs matter? A relative href like /pricing is meaningless once the link leaves the page. Resolution respects <base href> and the post-redirect URL, so every href in the output works standalone in a spreadsheet, a crawler queue, or a model's context.

Can I extract links from many pages at once? Yes - pass an array in urls, capped by maxUrls (default 50). One record and one $0.01 charge per page, and one bad URL never stops the others.

How are duplicate links handled? Deduplicated on href plus anchor text. The same nav link repeated in the footer collapses to one entry; the same target linked from two different phrases stays as two, because those are two different signals in an SEO audit.

Does it follow the links it finds? No. It reads one page per URL you pass and does not crawl. That is what keeps the price flat and the run bounded.

What happens on a page that is not HTML, or that fails to load? You get a record with an error field instead of links, the run continues, and that URL is not charged.


Built by Broke to Built.

For AI agents

This Actor is built to be called by software, not just by people.

  • Mount it directly as an MCP tool — no Store search, no ranking, just this one tool: https://mcp.apify.com/?actors=eliai/webpage-links-extractor
  • Or call it over HTTP and get the results in the same request: POST https://api.apify.com/v2/acts/eliai~webpage-links-extractor/run-sync-get-dataset-items
  • Pay with x402, without an Apify account. This Actor is whitelisted for agentic payments, so an agent holding USDC on Base can buy a prepaid token and spend it here. The minimum purchase is $1, the token balance is an absolute spending cap, and it expires 14 days after purchase.
  • Costs are predictable before you call. Pricing is pay-per-event (see Pricing above), so an agent can budget a run in advance instead of discovering the bill afterwards.
  • Send only the field you mean. If you pass the bulk field, it is used on its own; the single-value field is a fallback, never merged into your request. You are charged for the items you sent and nothing else.