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

Getting Started

Read any public link-in-bio page as structured JSON, and follow its links to where they really go. No account on Linktree or anywhere else — just your FetchLayer key.

1. Get your API key

Create an account and generate a FetchLayer API key from your dashboard. The same key works on every platform.

Create free account →

2. Read a page

Pass the full page address. Not a handle — spotify exists on a dozen services.

bash
curl -X POST https://api.fetchlayer.dev/link-in-bio/profile \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"profile":"https://linktr.ee/spotify"}'

The links are at profile.links[], not at the root

This is the one thing everyone gets wrong. On /profile the list is profile.links[], the count is profile.linkCount and the creator’s name is profile.identity.displayName. Only notes[] and pagesFetched sit at the top level. The /links route below is the one that puts links at the root.

A bare handle is a 400, on purpose

Sending {"profile":"nike"} returns “Handles are not unique across services, so "nike" is ambiguous. Pass the full profile URL, or name the provider.” If a handle is genuinely all you have, add "provider":"linktree".

3. Or just the links

Same page, narrower answer — and on this route links is at the top level. totalLinks reports how many the page had before kind and limit narrowed it, so a filter that matches nothing is visibly a filter.

bash
curl -X POST https://api.fetchlayer.dev/link-in-bio/links \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"profile":"https://linktr.ee/spotify","kind":"link","limit":100}'

4. Follow the links to where they really go

Set resolveDestinations and every link gains a destination: the final url, its host, the hop chain, the page title, and shortened when a shortener or affiliate redirector was involved. That is how you find the retailer behind a campaign link rather than the wrapper in front of it.

bash
curl -X POST https://api.fetchlayer.dev/link-in-bio/links \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"profile":"https://linktr.ee/spotify","resolveDestinations":true}'

curl -X POST https://api.fetchlayer.dev/link-in-bio/unwrap-link \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bennyblanco.lnk.to/TeOlvido"}'

Read destinationsResolved, not a null destination

A null destination means “not asked for” when destinationsResolved is false, and “could not be reached” when it is true — in which case unresolvedReason says why. Resolving is off by default because it turns one page fetch into one request per link: a 68-link page is a very different request from a 3-link one.

5. Triage a list of addresses first

Four services are readable here — Linktree, Lnk.Bio, AllMyLinks and solo.to — and twenty-six more are recognised with the reason they are not. Find out before you spend a page fetch.

bash
curl -X POST https://api.fetchlayer.dev/link-in-bio/resolve-url \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bento.me/someone"}'

curl -X POST https://api.fetchlayer.dev/link-in-bio/detect-provider \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bento.me/someone"}'

Knowing a service is dead is worth as much as reading a live one

/detect-provider answers a bento.me address with “Bento has closed and its addresses now redirect to Linktree; use the creator’s Linktree page instead”. Beacons, HeyLink, Direct.me and Lynk.id come back as walled behind bot verification; Komi, Pillar and Bio.fm as rendered after the page opens; Carrd as a general site builder with no link list at all. /resolve-url gives the same supported verdict for free, fetching nothing.

Empty pages, and broken ones

A page that is live but publishes nothing is a 200 with linkCount: 0 and the note “This page is live and published no links.” — a parked handle looks exactly like that. A page whose link list could not be read at all is a 502. The two are deliberately different statuses, so an empty list here genuinely means empty and you can alert on the 502 alone.

Coverage really is uneven between pages, and that is creators rather than the reader: on 16 September 2026, linktr.ee/selenagomez returned 68 links, shakira 11, spotify and adidas 6 each, nike 3, and bbc 0. All six were a 200.

Errors and retries

A 400 names the field to fix, and is also what a recognised-but-unreadable service returns. A 404 means no page exists at that address. A 502 means the page was fetched but could not be read — worth retrying once, and worth reporting if it persists. A 503 means the service was temporarily unavailable; wait before retrying.

Next steps