Link in Bio API — FetchLayer Docs
Documentation menu
FetchLayer FetchLayer API

Link in Bio API v1

Any link-in-bio page, as JSON or Markdown, from https://api.fetchlayer.dev/link-in-bio. A link page is the same object wherever it is hosted — a creator, a short bio and a list of outbound links — so one shape covers every service here and you write one parser, not four.

OpenAPI JSON

Read these fields

Two routes return the same links in different places, and mixing them up is the one mistake everyone makes with this API. This table is the short version of the whole reference.

What you want /profile /links
The link listprofile.links[]links[]
How many linksprofile.linkCountlinkCount
The creator’s nameprofile.identity.displayNamenot returned
Caveats about the readnotes[]notes[]
What it costpagesFetchedpagesFetched

There is no root-level links on /profile, and no identity on /links. notes and pagesFetched are always at the top level on both.

An empty list is an answer, not a failure

A page that is live but publishes nothing comes back as a normal 200 with linkCount: 0 and a note saying so — “This page is live and published no links.” A parked Linktree handle looks exactly like that, and so it should.

A page whose link list could not be found at all is a 502 instead. That is the whole point of the distinction: an empty list here genuinely means empty, so you can alert on 502 and ignore a zero, rather than treating every empty result as a possible parser regression.

Available endpoints

Pass the address, not the handle

profile takes a full page address: https://linktr.ee/spotify, or linktr.ee/spotify. A bare handle is a 400, and the message says why: “Handles are not unique across services, so "nike" is ambiguous. Pass the full profile URL, or name the provider.” If a handle really is all you have, send provider with it.

Four services readable, twenty-six recognised

Readable in this release: Linktree (the richest by some distance), Lnk.Bio, AllMyLinks and solo.to. Those are what /profile and /links return pages for.

Recognised but not readable: twenty-six more, each with the reason, which is worth as much as a successful read when you are triaging a list:

  • Behind bot verification — Beacons, HeyLink, Direct.me, Lynk.id. The page exists; a signed-out reader cannot fetch it.
  • Rendered after the page opens — Komi, Pillar, Bio.fm. There is no link list in the document that arrives.
  • Shut down — Bento, Linkpop, ContactInBio, Tap.bio. A bento.me address is answered with “Bento has closed and its addresses now redirect to Linktree; use the creator’s Linktree page instead”, which is a far better outcome than a failed fetch.
  • Not a link aggregator — Carrd builds general one-page sites, so there is no link list to read.

Run a list of pasted addresses through /resolve-url first — it fetches nothing and is free — and read only the ones it marks supported.

Coverage is uneven, and that is the data

Five real Linktree pages read on 16 September 2026: selenagomez 68 links, shakira 11, spotify 6, adidas 6, nike 3, and bbc 0 — a live handle with nothing on it. That spread is what creators publish, not a limit of the reader, and every one of those was a 200.

Following a link to where it really goes

Set resolveDestinations on either page route and every link gains a destination: the final url, its host, the hop chain, the page title, and shortened when the chain passed through a shortener or an affiliate redirector. It is off by default because it turns one page fetch into one request per link.

Check destinationsResolved on the /links response rather than reading a null destination as “goes nowhere” — it distinguishes “not asked for” from “could not be reached”, and when a chain really did fail, unresolvedReason says why.

For a single link, /unwrap-link does the same job on its own.

Paging and billing

A link page is one document, so there is no cursor here: limit caps how many entries come back, up to 500, and totalLinks reports how many the page had before kind and limit narrowed it.

Billing follows pages: one credit per page fetched, stated on every response as pagesFetched. Reading a page costs 1 whether it has 68 links or none. /resolve-url fetches nothing at all and is free; /detect-provider reports pagesFetched: 0 when it recognised the address from its shape alone.

Errors

  • 400 — the request is wrong, and the message names the field. Also what you get for a bare handle with no provider, and for a service that is recognised but cannot be read: “Beacons pages are behind bot verification and cannot be read by this service.”
  • 404 — no page exists at that address: “No Linktree profile exists at https://linktr.ee/…”
  • 502 — the page was fetched but its link list could not be read at all. This is the one to alert on.
  • 503 — the service was temporarily unavailable. Retry after a wait.