The _fbc cookie is a first-party cookie that stores Meta’s click ID, the fbclid added to your URL when someone clicks an ad, in the format fb.<subdomainIndex>.<creationTime>.<fbclid>. The Meta Pixel writes it when a visitor lands with ?fbclid= in the URL, and your server can build the same value itself. Its sibling _fbp identifies the browser.
Both values end up in the Conversions API, unhashed, as user_data.fbc and user_data.fbp. They matter more than their size suggests: Meta’s help center article about Event Match Quality ranks the click ID as a High-priority identifier, next to email, and the browser ID as Medium. Lose the fbclid and your Lead loses its most direct link to the ad click.
What are the _fbc and _fbp cookies?
Meta’s developer doc on ClickID and the fbp and fbc parameters defines both. The lifespan comes from Meta’s cookies policy.
_fbc | _fbp | |
|---|---|---|
| What it holds | Meta’s click ID (fbclid) | a random ID for the browser |
| Who sets it | the Meta Pixel, when the URL carries an fbclid; or your server | the Meta Pixel, when it uses first-party cookies and none exists yet |
| Needs an ad click | yes | no |
| Format | fb.<subdomainIndex>.<creationTime>.<fbclid> | fb.<subdomainIndex>.<creationTime>.<randomNumber> |
| Example | fb.1.1793787151204.IwAR2F4-dbP0l7Mn1IawQQGCINEz7PYXQvwjNwB_qa2ofrHyiLjcbCRxTDMgk | fb.1.1793787151880.1684203391 |
| Lifespan in Meta’s cookies policy | 90 days | 90 days |
| Conversions API field | user_data.fbc | user_data.fbp |
The fbclid in the example is the one Meta uses in its own documentation. What the fbclid identifies, and why it can’t be your only attribution key, is in the fbclid glossary entry.
The _fbc cookie format, field by field
Split the example on its dots:
| Part | Example | Meaning |
|---|---|---|
| version | fb | always fb |
| subdomainIndex | 1 | which domain the cookie is defined on: com = 0, example.com = 1, www.example.com = 2. Use 1 when you generate the value on a server without saving a cookie |
| creationTime | 1793787151204 | Unix time in milliseconds when the cookie was saved, here 4 November 2026, 10:12:31 UTC |
| fbclid | IwAR2F4-dbP0…TDMgk | the fbclid from the landing page URL, unchanged |
Two rules from Meta trip people up. The click ID is case sensitive: “do not apply any modifications before using, such as lower or upper case”. And in a stored cookie, the fbclid is the string after the last dot. Meta adds one caveat: values formed by its Parameter Builder library carry an extra appendix at the end.
To split a real value, or go the other way, decode an _fbc value or build one from a URL with the fbclid parser.
_fbp has the same structure with a random number in place of the click ID. The pixel generates that number to make each _fbp unique, so it identifies a browser rather than a click. Meta also says both values “are subject to change over multiple browser sessions” and recommends refreshing them with the latest value you have.
How to build fbc when the _fbc cookie is missing
The cookie can be missing for plenty of ordinary reasons: no pixel on the landing page, a pixel blocked by the browser or an extension, a visitor who submits before it loads. Meta documents the fix: you can still send fbc with a Conversions API event as long as there’s an fbclid in the URL of the current request.
- Read
fbclidfrom the landing page URL on the request that renders it. Don’t trim, lowercase or re-encode it. - Format it as
fb.1.<milliseconds>.<fbclid>. If you don’t save an_fbccookie, Meta says to use 1 as the subdomain index and, as creation time, the moment you first observed thefbclid, which is now. - Keep it. Meta offers two options: store the formatted value in your backend, or set
_fbcyourself as an HTTP cookie in the response with a 90-day expiry. If you set the cookie, do it only when none exists or when thefbclidin the URL differs from the one in the cookie, and make the subdomain index match the domain you set it on. - Send it with every event for that visitor, starting with the Lead. Meta recommends sending
fbcwith every Conversions API event.
In code, the backend option looks like this (saveClick stands for wherever you store the click):
// On the request that renders the landing page
const url = new URL(req.url, `https://${req.headers.host}`);
const fbclid = url.searchParams.get("fbclid"); // case sensitive: leave it as it is
if (fbclid) {
const fbc = `fb.1.${Date.now()}.${fbclid}`; // 1 and milliseconds: Meta's server-side rule
await saveClick({ clickId, fbclid, fbc });
}
When a visitor comes back through a second ad, the new fbclid replaces the old one: Meta asks for the most recent value whether you keep it in a cookie or in your database. Building the value server-side doesn’t change your consent obligations, only where the value is computed.
DropCPL logs the fbclid with the click, server-side, on the same domain that serves your landing page, and sends the matching fbc with the Lead event. The value never depends on a cookie written by JavaScript. Start free →
How long do the _fbc and _fbp cookies last?
Meta’s cookies policy gives both a lifespan of 90 days, and Meta recommends the same 90 days if you set _fbc yourself. That’s what Meta asks for. On Safari, the browser decides how much of it you get, based on how the cookie was set.
Why Safari shortens JavaScript cookies
The Meta Pixel is a script, so the cookies it writes are JavaScript cookies, and Safari’s Intelligent Tracking Prevention is hard on those. WebKit’s tracking prevention documentation lists two rules:
- ITP deletes all cookies created in JavaScript, along with other script-writeable storage, after 7 days without user interaction with the website.
- When ITP detects link decoration, meaning click IDs added to the URL and picked up by script on the landing page, it caps cookies created in JavaScript on that landing page to 24 hours.
An ad click that lands with ?fbclid= and a pixel that copies it into _fbc is the pattern the second rule describes.
Why a server-set cookie fares better
Both rules apply to cookies created in JavaScript. A cookie your server sets with a Set-Cookie header isn’t covered by them, and WebKit’s own table shows no cap when there’s no cloaking. Cloaking is the exception: ITP caps any cookie set in the HTTP response to 7 days when the request goes through third-party CNAME cloaking or third-party IP address cloaking. For the IP check, WebKit currently treats two addresses as different parties when one is IPv4 and the other IPv6, or when they share less than half their bits.
So “set it on the server” only helps when the server is genuinely yours. The cleanest case is the cookie arriving in the same response as the landing page HTML, because then the server setting it is the website. That’s the design behind first-party tracking, and the longer story is in tracking after iOS.
| How the cookie is set | What Safari’s ITP does |
|---|---|
| Written by JavaScript (the Meta Pixel, any tag) | deleted after 7 days without interaction with the site; 24 hours when link decoration is detected |
Set-Cookie from a third-party server cloaked behind your subdomain (CNAME or IP) | capped at 7 days |
Set-Cookie in the response that renders the landing page | no ITP cap |
When there’s no fbclid to read
Safari can also remove the parameter before it reaches anyone. Its Link Tracking Protection strips “a subset of query parameters that have been identified as being used for pervasive cross-site tracking granular to users or clicks”, before the navigation happens. It’s on in Private Browsing, and in regular browsing for users who switch on Advanced Tracking and Fingerprinting Protection for all browsing (WebKit’s Private Browsing 2.0 post). Apple doesn’t publish the list, but a per-click ID like fbclid is exactly what it describes.
In Private Browsing, third-party scripts also get the URL without its query string, so a pixel loaded from Meta’s domain can’t read fbclid even when it survives. Your server sees the full request URL. When the parameter is gone, nobody can build fbc: send fbp if you have it, plus hashed email and phone, and don’t invent a value.
How to send fbc and fbp in the Conversions API
Both go in user_data, as plain strings. Meta’s reference of customer information parameters marks them “Do not hash”, like the IP address and the user agent, while email and phone must be hashed.
{
"user_data": {
"em": ["10928b45363b7d849e040470c3277657f8177ef5a953a092b4302f149757a02e"],
"fbc": "fb.1.1793787151204.IwAR2F4-dbP0l7Mn1IawQQGCINEz7PYXQvwjNwB_qa2ofrHyiLjcbCRxTDMgk",
"fbp": "fb.1.1793787151880.1684203391",
"client_ip_address": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"client_user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
}
}
The full Lead payload, with event_id, is in Meta Pixel and CAPI deduplication, where fbp also shows up as one of Meta’s fallback deduplication keys. How these values feed the score is in Event Match Quality for lead generation.
Mistakes that break fbc
- Changing the
fbclid. Lowercasing, trimming or re-encoding it breaks a case-sensitive value. - Hashing
fbcorfbp. Both are do-not-hash fields. - Seconds instead of milliseconds.
creationTimeis in milliseconds; a 10-digit timestamp is the giveaway. - Timestamping the Lead instead of the click. Use the moment you first saw the
fbclid, not the moment the form was submitted. - Rewriting the value on every visit. Set it only when there’s none or when the
fbclidhas changed. - Keeping an old click over a new one. The most recent
fbclidwins. - Inventing
fbcfor visits without anfbclid. There’s no click ID to send, so send nothing. - A redirect that drops the query string. If a hop before the landing page loses the parameters, the
fbclidnever reaches your server, which is why the tracking domain should serve the landing page itself.