---
title: 'What is fbclid? How it relates to fbp and fbc'
description: 'Learn what fbclid means in a URL, how it becomes fbc, how fbp differs, and how to pass valid browser identifiers to Meta CAPI.'
published_at: 2026-09-03
last_updated: 2026-09-10
format: Explainer
---

# What is fbclid? How it relates to fbp and fbc

`fbclid` is a click identifier that can appear in the URL when someone follows a link from Facebook. In Meta conversion tracking, it supplies click context used to construct `fbc`. It is different from `fbp`, which supplies browser context, and `event_id`, which identifies a conversion.

A fictional landing URL might look like this:

```text
https://shop.example/products/widget?fbclid=IwAR3ExampleClickIdentifier
```

Here, `IwAR3ExampleClickIdentifier` is the raw `fbclid` value. Meta's [official server SDK](https://github.com/facebook/facebook-nodejs-business-sdk/blob/main/src/objects/serverside/user-data.js) documents that `fbc` can come from the `_fbc` cookie or be generated from this URL parameter. Preserve the click's capture time when formatting it as `fbc`; do not send the raw URL value as a complete `fbc`.

[fbp and fbc are customer information parameters in Meta's Conversions API](https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters). Send both unchanged, without hashing, when your consent policy permits their use. If no Meta click identifier was captured, omit `fbc`.

## Key takeaways

- `fbp` describes browser context; `fbc` describes a Meta ad click.
- Send the original values unchanged. Do not SHA-256 hash either field.
- Never invent `fbc` when no `fbclid` was captured.
- Preserve the time when the click was first observed, not the later purchase time.
- In a Plainrouter event request, put both values under `click_ids`, not `user_data`.
- Capture, persist, and send them only when your consent policy permits it.

## What is the difference between fbp, fbc, and fbclid?

`_fbp` and `_fbc` are cookie names; `fbp` and `fbc` are the corresponding CAPI field names. `fbclid` is the click ID in a landing-page URL, before it is combined with a timestamp to form `fbc`.

| Field    | Represents                                                   | Typical source                                             | When it may be absent                                                             |
| -------- | ------------------------------------------------------------ | ---------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `fbp`    | A browser associated with a first-party Meta browser cookie. | The `_fbp` cookie created after permitted browser storage. | The browser blocks storage, consent is not granted, or no integration created it. |
| `fbc`    | A captured Meta ad click associated with the visitor.        | A landing-page `fbclid`, combined with its capture time.   | No permitted current or retained Meta click identifier is available.              |
| `fbclid` | The raw click identifier added to a Meta ad landing URL.     | The landing request's URL query string.                    | The URL has no Meta click parameter, or a redirect removed it.                    |

None of these identifiers identifies the conversion itself. Use `event_id` to identify one logical event and deduplicate its browser and server copies. Use `fbp` and `fbc` to provide permitted browser and click context for matching and attribution.

## What format should fbp and fbc use?

Meta browser identifiers commonly use these structures:

```text
fbp: fb.1.<creation-time-milliseconds>.<random-decimal>
fbc: fb.1.<click-time-milliseconds>.<fbclid>
```

For example:

```text
fb.1.1786271000000.1234567890
fb.1.1786271000000.IwAR3ExampleClickIdentifier
```

The timestamp inside `fbc` belongs to the click capture. If the visitor purchases two days later, do not rebuild `fbc` with the purchase time. Keep the originally captured value.

An `fbclid` is not itself an `fbc`. If you own the capture flow, record the time when the landing page first receives `fbclid` and construct the browser identifier at that boundary. Do not manufacture a placeholder for visits without one.

## How the values reach a server event

The two values can have different origins but travel with the same eligible event:

```text
Meta ad click ── fbclid + capture time ── fbc ──┐
                                                ├─ click_ids ─ Meta user_data
Consented browser storage ─────────────── fbp ──┘

Logical conversion ───────────────── event_id ── deduplication identity
```

This separation matters when debugging. A correct `event_id` does not compensate for missing match context, and a valid `fbc` does not deduplicate two copies of a purchase.

## How do you capture fbp and fbc after consent?

### Use the managed browser path

Plainrouter's generated Signals snippet can manage the browser values after full advertising consent. It captures an eligible `fbclid`, creates or reads the browser identifier, and includes the available values with consented events. When consent is denied or withdrawn, Plainrouter-owned browser identifiers are not kept for later advertising delivery.

With that managed path, do not add your own competing `_fbp` or `_fbc` implementation. Track the business event once and let the configured destination use the eligible context:

```js
const eventId = await signalq('track', 'Purchase', {
    value: '49.90',
    currency: 'EUR',
    order_id: 'ORDER-1042',
});

console.log('Accepted event ID', eventId);
```

### Transfer existing cookies to your server

If your application sends the server event manually, read the browser values from the consenting request that belongs to the visitor. This helper preserves embedded `=` characters and ignores malformed cookie segments:

```ts
import type { IncomingMessage } from 'node:http';

function decodeCookiePart(value: string): string | undefined {
    try {
        return decodeURIComponent(value);
    } catch {
        return undefined;
    }
}

function readCookies(header: string | undefined): Record<string, string> {
    return Object.fromEntries(
        (header ?? '').split(';').flatMap((part) => {
            const separator = part.indexOf('=');

            if (separator <= 0) return [];

            const name = decodeCookiePart(part.slice(0, separator).trim());
            const value = decodeCookiePart(part.slice(separator + 1).trim());

            return name && value ? [[name, value] as const] : [];
        }),
    );
}

function readMetaClickIds(request: IncomingMessage) {
    const cookies = readCookies(request.headers.cookie);

    return {
        ...(cookies._fbp ? { fbp: cookies._fbp } : {}),
        ...(cookies._fbc ? { fbc: cookies._fbc } : {}),
    };
}
```

Use a reviewed cookie parser in a production framework when one is available. Do not put these values in URLs, analytics logs, or client-visible error reports just to move them between layers.

## Send the values through Plainrouter

The Plainrouter TypeScript SDK accepts advertising identifiers under `click_ids`. Building on the helper above, this server handler carries only values present on the incoming request:

```ts
import type { IncomingMessage } from 'node:http';
import { configurePlainrouter, createEvent } from '@plainrouter/sdk';

const signalSecret = process.env.PLAINROUTER_SIGNAL_SECRET;

if (!signalSecret) {
    throw new Error('PLAINROUTER_SIGNAL_SECRET is required');
}

configurePlainrouter({ signalTrackerSecret: signalSecret });

export async function sendPurchase(request: IncomingMessage, order: { id: string; total: string }) {
    const clickIds = readMetaClickIds(request);

    const { data, response } = await createEvent({
        body: {
            event_id: `purchase:${order.id}`,
            event_name: 'Purchase',
            event_source: 'https://shop.example/checkout/success',
            action_source: 'website',
            consent_basis: 'consent',
            consent: {
                ad_storage: 'granted',
                ad_user_data: 'granted',
                ad_personalization: 'granted',
                captured_at: new Date().toISOString(),
                source: 'checkout_cmp',
            },
            click_ids: clickIds,
            value_data: {
                value: order.total,
                currency: 'EUR',
                order_id: order.id,
            },
        },
    });

    if (!data) {
        const status = response?.status ?? 'no HTTP response';
        throw new Error(`Event request failed: ${status}`);
    }

    return data;
}
```

The example assumes the consent object comes from the site's real consent workflow. Copying `granted` into a request does not establish permission by itself.

Plainrouter accepts Meta and other advertising identifiers under `click_ids`. During eligible Meta delivery, valid `fbp` and `fbc` values become Meta `user_data` fields. Values that do not follow the expected Meta browser-ID shape are not useful delivery context.

## Should you hash fbp and fbc before sending them to Meta?

No. Meta expects `fbp` and `fbc` in their documented browser-ID formats rather than as SHA-256 hashes. Send valid values exactly as captured. The table below describes the Plainrouter API; direct Meta CAPI requests use Meta's own field names and hashing rules.

| Input               | Plainrouter request location | Hash before sending?                                                          |
| ------------------- | ---------------------------- | ----------------------------------------------------------------------------- |
| `_fbp` cookie value | `click_ids.fbp`              | No                                                                            |
| `_fbc` cookie value | `click_ids.fbc`              | No                                                                            |
| Email address       | `user_data.email`            | No; Plainrouter normalizes and hashes supported raw identity fields for Meta. |
| Phone number        | `user_data.phone`            | No; Plainrouter normalizes and hashes supported raw identity fields for Meta. |
| Event identity      | `event_id`                   | No; use the same stable value for retries and paired delivery.                |

Hashing `fbp` or `fbc` destroys the structure Meta expects. Placing them under `user_data` in the Plainrouter request also bypasses the public field contract; use `click_ids`.

## What these values can and cannot improve

Available, valid browser context can help Meta associate a server event with a browser or ad click. It does not guarantee attribution, a particular Event Match Quality score, or a campaign outcome.

Do not optimize for field presence by fabricating identifiers. The correct state for a direct visit is often an `fbp` without `fbc`. The correct state before permitted browser storage may be neither value.

## Common fbp and fbc mistakes

| Mistake                                                     | Why it fails                                                      | Better approach                                           |
| ----------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------- |
| Hashing the values.                                         | Meta no longer receives the expected browser-ID structure.        | Send the captured values unchanged.                       |
| Treating `fbclid` as a ready-made `fbc`.                    | The formatted identifier is missing its prefix and capture time.  | Preserve the landing click and its original capture time. |
| Creating `fbc` for every visit.                             | Direct and non-Meta visits are falsely labeled as Meta clicks.    | Omit `fbc` when no valid `fbclid` exists.                 |
| Rebuilding `fbc` at purchase time.                          | The timestamp no longer represents the ad click.                  | Reuse the value captured on landing.                      |
| Reading cookies before consent permits it.                  | Transport location does not replace the site's consent decision.  | Gate capture and use through the real consent workflow.   |
| Putting the values in `user_data` in a Plainrouter request. | The request no longer follows the public Plainrouter event shape. | Use `click_ids.fbp` and `click_ids.fbc`.                  |
| Expecting them to deduplicate events.                       | They provide match context, not conversion identity.              | Coordinate browser and server copies with `event_id`.     |

## How to debug missing browser identifiers

A missing `fbc` is only a capture problem if the visit supplied a Meta click identifier that your consent policy allowed you to retain. Check the landing request before changing the conversion payload.

1. Start with one known visit and record whether its landing URL actually contained `fbclid`.
2. Confirm the site's resolved consent state before the identifiers are read or created.
3. Inspect `_fbp` and `_fbc` in browser storage. An absent `_fbc` is expected when no Meta click occurred.
4. Confirm the server request carries the original values under `click_ids` without hashing or reformatting.
5. Confirm the request belongs to the same visitor and is not coming from a background system with no browser context.
6. Inspect the accepted Plainrouter event and its destination delivery state separately.
7. Confirm the event is eligible for the configured Meta destination before treating missing downstream fields as a capture bug.
8. Use Meta Test Events and Events Manager diagnostics to inspect the received server event.

Debug the acquisition path and the conversion path separately. The click can be lost on the landing request even when the later purchase request is otherwise correct.

## Frequently asked questions

### Is fbp the same as a Meta Pixel ID?

No. A Pixel or dataset ID identifies the Meta data source. `fbp` is browser context associated with a visitor's first-party cookie.

### Is fbc always required for Meta CAPI?

No. `fbc` should be present only when a valid Meta click identifier was captured. A direct or organic visit can still carry a retained `fbc` from an earlier Meta click when your policy permits it. A visit without a current or retained Meta click identifier should not be assigned one.

### Can I send fbclid directly as fbc?

No. `fbclid` is only the click-ID portion. An `fbc` also includes the `fb` prefix, domain index, and original creation timestamp in milliseconds. Send the complete captured `_fbc` value, or construct the documented format when you capture an eligible landing-page click. Do not use the later purchase time.

### Can the server create fbp?

A server should normally transfer the value created in permitted browser context rather than inventing a browser identity during a backend job. If the request has no browser context, omit it.

### How long should I keep fbp and fbc?

Follow Meta's current guidance, browser limits, and your consent and retention policy. Plainrouter's managed browser path requests a 90-day cookie lifetime, but browsers can shorten it.

### Do fbp and fbc replace email or phone matching?

No. They provide browser and click context. Permitted customer information is a separate input with different normalization and hashing rules.

### Do fbp and fbc replace event_id?

No. `event_id` identifies the logical conversion and coordinates retries or browser/server deduplication. `fbp` and `fbc` supply matching and attribution context.

## Sources

- [Meta: Conversions API customer information parameters](https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters)
- [Meta: Conversions API server event parameters](https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event)
- [Meta Business SDK for Node.js](https://github.com/facebook/facebook-nodejs-business-sdk#conversions-api)
- [Plainrouter Conversion API reference](https://plainrouter.com/docs/api/conversions)
- [Plainrouter TypeScript SDK request types](https://github.com/plainrouter/sdk/blob/v0.5.1/packages/sdk/src/generated/types.gen.ts)

## Related guides

- [Troubleshoot missing Meta Pixel and CAPI events](/library/meta-capi-missing-duplicate-events)

- [Meta Event Match Quality: diagnose a low or falling score](/library/meta-event-match-quality)
- [How does Meta event_id deduplication work?](/library/meta-event-id-deduplication)
- [Can you use Meta CAPI without Google Tag Manager?](/library/meta-capi-without-gtm)
- [Track events and consent](https://plainrouter.com/docs/signals/track-events)
- [How does consent work for server-side tracking?](/library/server-side-consent)

## Inspect browser identifiers locally

The interactive version of this guide includes an fbp/fbc decoder below. Paste a bare value or `_fbp=` / `_fbc=` cookie value to check its shape and timestamp. The check stays in your browser and does not verify attribution.

To construct fbc from a real captured fbclid, supply the original capture time in Unix milliseconds and the subdomain index for the cookie domain. Do not use the purchase time or invent an identifier for a visit without a captured click.
