Get a link-in-bio page in full
One creator’s link page, by its address: who they are, how the page looks, what it sells, what stands in front of it, and every link on it. Read the response shape before anything else, because it is the one thing callers get wrong: **the links are at `profile.links[]` and the count at `profile.linkCount`, not at the root**, and the creator’s name is at `profile.identity.displayName`. `notes` and `pagesFetched` are the only fields at the top level worth reading. Alongside them `profile` carries provider, providerName, handle, url, status, identity, theme, monetization, gates, socialLinks and source. Pass `resolveDestinations` to follow every link through its redirects and fill in `destination` on each one. A page that is live but publishes nothing comes back as a normal 200 with `linkCount: 0` and a note saying so — and that genuinely means empty, because a page whose link list could not be read at all is a 502 instead. The two statuses are different on purpose, so a caller can alert on one and ignore the other. A page the service has taken down answers with `status: "suspended"` rather than an error. Billing: 1 credit.
/profile Pages https://api.fetchlayer.dev/link-in-bio/profile Headers
Authorization string required Bearer token — your FetchLayer API key.
Parameters
profile string required The full page address — https://linktr.ee/spotify, or linktr.ee/spotify. Not a bare handle: "spotify" alone is a 400 saying handles are not unique across services. A bare handle works only when `provider` is given too.
provider string optional The service a bare handle belongs to (linktree, lnkbio, allmylinks, solo and 26 more). Required when `profile` is a handle rather than an address, and ignored when it is an address.
resolveDestinations boolean optional Follow every link through its redirects to where it really lands, filling in `destination`. Off by default: it turns one page fetch into one request per link, so a 68-link page is far slower than a 3-link one. (default: false)
format string optional json or markdown. Markdown returns a rendered summary instead of the structured record. (default: json)
timeoutMs integer optional Time limit for the request, in milliseconds (max 600000).
Response Fields
profile
Get a link-in-bio page in full
transport string The upstream source. Always "link-in-bio-page".
resultType string Which route produced this record — profile, links, detect-provider, unwrap-link or resolve-url.
requestedUrl string The address this result corresponds to.
scrapedAt string ISO 8601 timestamp of the read.
blocked boolean Always false on a successful response.
notes string[] Caveats you can act on — a page that is live but publishes no links, a service that publishes no theme or plan details, a destination that could not be reached. Read these: an empty result always arrives with one.
pagesFetched number Pages fetched, which is what the request costs: one credit per page. detect-provider reports 0 when it recognised the address from its shape alone, and resolve-url fetches nothing at all.
profile.provider string Short, stable id for the service (linktree, lnkbio, allmylinks, solo…). A service that rebrands keeps its id, so a stored value does not break.
profile.providerName string The service’s public name, for display.
profile.handle string The creator’s handle on that service.
profile.url string The page’s canonical public address.
profile.status string active (live and readable), suspended (the page exists but the service took it down) or inactive.
profile.identity.displayName string The name shown at the top of the page. This is where the creator’s name lives — not at the root.
profile.identity.bio string The bio under the name, or null.
profile.identity.avatarUrl string The avatar, or null.
profile.identity.verified boolean True where the service marks the account verified, null where it has no such concept.
profile.identity.plan string "free" or "paid" where the service publishes it — the best public signal that a page belongs to someone serious — or null.
profile.identity.country string ISO 3166-1 alpha-2, where published.
profile.identity.createdAt string When the page was created, ISO 8601, where published.
profile.identity.unclaimed boolean True where the service marks the page as never claimed by its owner.
profile.theme object The page’s colours and font, or null where the service publishes none.
profile.monetization object Whether the page sells anything or takes tips.
profile.gates object[] Gates standing in front of the whole page. Empty when it is freely readable.
profile.socialLinks object[] The social icon row, separate from the button list.
profile.links object[] Every entry on the page, in the page’s own order. This is the link list — not a root-level `links`.
profile.links[].id string The service’s own id for the entry, stable across reads, or null.
profile.links[].kind string link, embed, product, social, heading or group. Coarse on purpose, so it stays stable as services change their own vocabularies.
profile.links[].providerType string The service’s own label for the entry, verbatim ("classic"). Free-form — do not switch on it.
profile.links[].title string The label shown on the button.
profile.links[].description string Supporting copy under the title, or null.
profile.links[].url string Where the page sends a visitor. Null on a heading, a group, or a gated link whose target is withheld.
profile.links[].position number 0-based position in the page’s own order.
profile.links[].parentId string The id of the group or heading this sits under, or null at the top level.
profile.links[].thumbnail object The image on the button, or null.
profile.links[].tracked boolean True when clicks are routed through the service’s own click tracker rather than straight to `url`.
profile.links[].monetized boolean True when the link earns the creator money — an affiliate link, a product, a paid unlock.
profile.links[].product object Price and currency where the entry sells something, or null.
profile.links[].gates object[] Gates on this specific link — an age check, a payment, an email capture. Empty when it is freely clickable.
profile.links[].destination object Where `url` actually lands, when destinations were resolved: url, host, status, hops, truncated, title, shortened and unresolvedReason. Null when they were not asked for — check `destinationsResolved` rather than reading null as "goes nowhere".
profile.linkCount number How many entries are in `profile.links`. 0 on a live page that publishes nothing, with a note saying so.
profile.source string "page-payload" or "page-markup" — how completely the page could be read. A field absent under one may be present under the other, so this says which you got.
Request
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"}'Response
{
"blocked": false,
"requestedUrl": "https://linktr.ee/spotify",
"scrapedAt": "2026-09-16T20:41:12.804Z",
"transport": "link-in-bio-page",
"notes": [],
"resultType": "profile",
"pagesFetched": 1,
"profile": {
"provider": "linktree",
"providerName": "Linktree",
"handle": "spotify",
"url": "https://linktr.ee/spotify",
"status": "active",
"identity": {
"displayName": "@spotify",
"bio": null,
"avatarUrl": "https://ugc.production.linktr.ee/...",
"verified": null,
"plan": null,
"country": null,
"createdAt": null,
"unclaimed": null
},
"theme": null,
"monetization": {
"sellsProducts": false,
"acceptsTips": false
},
"gates": [],
"socialLinks": [],
"links": [
{
"id": "9964805",
"kind": "link",
"providerType": "classic",
"title": "Playlist 1",
"description": null,
"url": "https://open.spotify.com/user/0658h6ocit7uqryixhxt0uivc/playlist/4Zv9I6yJwjuPXZbB3e1Rx8?si=tQaQ38ioQRCrbS7k87rFhw",
"position": 0,
"parentId": null,
"thumbnail": null,
"tracked": false,
"monetized": false,
"product": null,
"gates": [],
"destination": null
}
],
"linkCount": 6,
"source": "page-payload"
}
}