Skip to content

traceparent Decoder — W3C Trace Context

Stop counting hex digits. Free online traceparent decoder — runs in your browser, nothing uploaded. Trace ID, span ID, all 8 trace-flags bits, tracestate check, Datadog/X-Ray/B3 conversion.

No Tracking Runs in Browser Free
Everything is decoded locally in your browser — the headers you paste never leave this device. Open the Network panel and watch it stay silent, or go offline entirely.
Try an example
Field breakdown
Version
00
Trace ID
4bf92f3577b34da6a3ce929d0e0e4736
Parent ID (span ID)
00f067aa0ba902b7
Trace flags
01
trace-flags, bit by bit
Bit Mask Name State
0 0x01 sampled 1
1 0x02 random-trace-id 0
2 0x04 reserved 0
3 0x08 reserved 0
4 0x10 reserved 0
5 0x20 reserved 0
6 0x40 reserved 0
7 0x80 reserved 0

Read these with a bitwise AND. Comparing the whole byte to 01 misreports any trace that also carries a reserved bit.

Other propagation formats
x-datadog-trace-id
11803532876627986230
x-datadog-tags: _dd.p.tid
4bf92f3577b34da6
x-datadog-parent-id
67667974448284343
AWS X-Ray trace ID
1-4bf92f35-77b34da6a3ce929d0e0e4736
b3 (single header)
4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1
X-B3-TraceId
4bf92f3577b34da6a3ce929d0e0e4736
X-B3-SpanId
00f067aa0ba902b7
X-B3-Sampled
1

Datadog carries the lower 64 bits of the trace ID as a decimal string and the higher 64 bits as hex in a tag. Passing the whole 128-bit value as decimal is the classic reason a trace ID from your logs finds nothing in the UI.

An X-Ray ID embeds a 32-bit timestamp; a W3C trace ID does not carry a timestamp at all. The date below is only meaningful if the identifier actually originated in X-Ray.

tracestate members 2/32
# Key Value Status
1 rojo 00f067aa0ba902b7 OK
2 congo t61rcWkgMzE OK

traceparent Format: Field Anatomy

traceparent Format: Field Anatomy
Field Hex digits Bytes Meaning Invalid value
version 2 1 Format version. Always 00 today; ff is forbidden. ff
trace-id 32 16 Identifies the whole trace end to end. All zeros
parent-id 16 8 Identifies the calling span, not the request. All zeros
trace-flags 2 1 An 8-bit field — read it bit by bit, never as a boolean.

trace-flags Values: 00, 01, 02 and 03 Explained

trace-flags Values: 00, 01, 02 and 03 Explained
Hex Binary sampled random-trace-id Meaning
00 00000000 0 0 Upstream chose not to sample — look at the caller, not your service.
01 00000001 1 0 Recorded normally. This is what you see most of the time.
02 00000010 0 1 Random trace ID declared, but not sampled.
03 00000011 1 1 Recorded, and the trace ID is declared uniformly random.

bit 0 — The caller recorded this trace. Clear means it deliberately chose not to.

bit 1 — Level 2: the right-most 7 bytes of the trace ID are uniformly random.

bit 2-7 — Reserved. Must be ignored, and cleared on outbound requests.

Field widths, invalid values, flag bit semantics and the tracestate limits on this page were checked against the published specification text rather than secondary write-ups. — Go Tools Engineering · Jul 22, 2026

Built directly against the W3C Trace Context recommendation and the Level 2 candidate recommendation, with the parser covered by unit tests for every valid and invalid form the specification names.

What Is the traceparent Header?

traceparent is the HTTP header that carries a distributed trace from one service to the next. Before it was standardised, every tracing vendor propagated context in its own header, so a request that crossed systems lost its identity at the boundary. The W3C Trace Context specification fixed that with a single, deliberately small format: version-trace-id-parent-id-trace-flags, four hexadecimal fields joined by dashes, 55 characters in total for the current version.

Each field does one job. The version is always 00 today, and ff is forbidden outright. The trace-id is 16 bytes identifying the whole request end to end — it stays constant across every hop. The parent-id is 8 bytes identifying the immediate caller's span, so unlike the trace-id it changes at every hop. The trace-flags byte is where most confusion lives: it looks like a boolean because 01 is by far the most common value, but it is eight bits. Bit 0 is sampled. Bit 1, added in Trace Context Level 2, is random-trace-id, asserting that the right-most seven bytes of the trace ID are uniformly random so that downstream systems may sample or shard on them. The remaining six bits are reserved, which is precisely why the field must be read with a bitwise AND rather than compared for equality.

A companion header, tracestate, carries vendor-specific key-value pairs alongside it, capped at 32 members. That ceiling explains a puzzling symptom: vendor data that is present at the edge and gone several hops later, because intermediaries began dropping entries once the list grew past the limit. The header became genuinely universal once OpenTelemetry adopted it, and this page decodes all of it — fields, bits, tracestate members and the equivalent identifiers for other propagation formats — without sending anything anywhere.

# The header as it travels on the wire
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
tracestate:  rojo=00f067aa0ba902b7,congo=t61rcWkgMzE

# Read the four fields apart
#   version     00
#   trace-id    4bf92f3577b34da6a3ce929d0e0e4736   (16 bytes, whole request)
#   parent-id   00f067aa0ba902b7                   (8 bytes, calling span)
#   trace-flags 01                                 (bit 0 set = sampled)

# Send one yourself
$ curl -H 'traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01' \
       https://example.com/api

Key Features

Every field, split and copyable

Version, trace-id, parent-id and trace-flags each get their own row and their own copy button, so lifting a 32-character trace ID into a query takes one click instead of a careful drag.

trace-flags read as eight bits

The flags byte is expanded into all eight positions with their hexadecimal masks. Bit 0 is sampled, bit 1 is the Level 2 random-trace-id flag, and the reserved bits are shown rather than silently discarded.

Datadog, X-Ray and B3 conversion

The lower 64 bits as a decimal Datadog trace ID, the higher 64 bits as the tag that travels with it, the X-Ray 1-{8}-{24} form, and both the single and multi-header B3 layouts — all computed with BigInt so nothing overflows.

Diagnoses, not just verdicts

An all-zero trace ID is explained as tracing that never initialised; a cleared sampled bit is explained as a decision made upstream. Knowing which of the two you are looking at is usually the whole debugging session.

tracestate with the 32-member ceiling

Members are listed with per-member key and value validation and a running count against the specification's limit — the limit that explains why vendor data vanishes a few hops downstream.

Nothing leaves your browser

Parsing is plain string and BigInt arithmetic with no dependencies and no network calls, verified by an automated contract test on every build. Copy link uses the URL fragment, which is never transmitted.

traceparent Examples, Decoded

The specification's own example, decoded

00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
version 00 · trace-id 4bf92f3577b34da6a3ce929d0e0e4736 · parent-id 00f067aa0ba902b7 · trace-flags 01 (sampled)

Four dash-separated fields, 55 characters in total for version 00. The trace-id identifies the entire request as it crosses every service; the parent-id — often called the span ID — identifies only the immediate caller, which is why it changes on every hop while the trace-id does not. The trailing 01 is a full byte, not a boolean: bit 0 is set, so the caller recorded this trace.

trace-flags 00 — the caller decided not to record

00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00
Valid header · sampled bit clear

This header is perfectly valid, and that is the point. A cleared sampled bit is an instruction from upstream, not a defect in your service: whoever called you evaluated their sampler and chose not to record. Chasing missing spans in your own configuration here wastes hours. The question to ask is which service is calling you, sending a parent span, and deciding not to sample the trace.

An all-zero trace ID means tracing never started

00-00000000000000000000000000000000-00f067aa0ba902b7-01
Invalid — all-zero trace-id

The specification declares an all-zero trace-id invalid, and requires that the whole traceparent be ignored. It is worth knowing what it signals in practice: not "a trace that has no data yet", but an SDK that was never initialised, or a middleware injecting a placeholder header. The same rule applies to an all-zero parent-id.

The same trace ID in Datadog's format

00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
x-datadog-trace-id 11803532876627986230 · _dd.p.tid 4bf92f3577b34da6

Datadog carries the lower 64 bits of a 128-bit trace ID as a decimal string, and the higher 64 bits as hexadecimal in a separate tag. Feed the whole 128-bit value in as decimal and you get a number that matches nothing — which is exactly why this conversion turns up again and again in tracer issue trackers. The lower half here is a3ce929d0e0e4736, and 64 bits exceeds what a JavaScript number can hold, so this page does the arithmetic with BigInt.

How to Use the traceparent Decoder

  1. 1

    Paste the traceparent header

    Drop in the raw header value — for example 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01. Decoding happens as you type; there is no button to press.

  2. 2

    Read the four fields apart

    Version, trace-id, parent-id and trace-flags are split into their own rows, each with a copy button, so you can lift just the trace ID into a query without hand-selecting 32 characters.

  3. 3

    Check the flags bit by bit

    The trace-flags byte is expanded into all eight bits with their masks, so sampled and the Level 2 random-trace-id flag are visible individually rather than hidden inside a two-character value.

  4. 4

    Convert to your backend's format

    Datadog, AWS X-Ray and both B3 forms are generated underneath, including the lower-64-bit decimal trace ID that Datadog expects and the higher-64-bit tag that travels alongside it.

  5. 5

    Add tracestate and share the result

    Paste a tracestate header to list its members with per-member validation and a count against the 32-member limit, then use Copy link to capture the exact state in a URL you can drop into a ticket.

Common traceparent Mistakes

Comparing the whole flags byte to 01

This treats an eight-bit field as an enumeration. A trace that is sampled and also carries the Level 2 random-trace-id flag has flags 03, and the equality check reports it as not sampled.

✗ Wrong
if (traceFlags === 0x01) { record(); }
✓ Correct
if (traceFlags & 0x01) { record(); }

Converting all 128 bits to one decimal number

Datadog expects the lower 64 bits as decimal and the higher 64 bits as hexadecimal in a separate tag. Passing the full value as one decimal number produces an identifier that matches nothing.

✗ Wrong
x-datadog-trace-id: 100985939111033328018442752961257817910
✓ Correct
x-datadog-trace-id: 11803532876627986230
x-datadog-tags: _dd.p.tid=4bf92f3577b34da6

Rejecting any version that is not 00

The specification asks parsers to read what they recognise from a higher version and tolerate trailing fields. Rejecting outright restarts the trace and breaks the link across the boundary.

✗ Wrong
if (version !== '00') throw new Error('bad traceparent');
✓ Correct
if (version !== '00' && header.length >= 55) { /* parse the known prefix */ }

Emitting uppercase hexadecimal

The grammar admits lowercase only. An uppercase trace ID carries the right value and is still rejected by a conforming receiver, which makes it a particularly frustrating bug to spot by eye.

✗ Wrong
traceparent: 00-4BF92F3577B34DA6A3CE929D0E0E4736-00F067AA0BA902B7-01
✓ Correct
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

What You Can Do with the traceparent Decoder

Work out why a trace has no spans
Paste the incoming header and read the sampled bit. If it is clear, the trace was never going to be recorded and the answer lies with the caller, not with your instrumentation — a distinction that saves a great deal of time spent auditing your own sampler configuration.
Find a trace that your backend cannot
When a trace ID copied from application logs returns nothing in Datadog, the format is usually the culprit. Convert it here to see the lower-64-bit decimal identifier the API expects, along with the higher-64-bit tag that has to accompany it.
Verify headers your gateway injects
Proxies and service meshes generate trace context on the way in. Paste what actually arrived to confirm the length, lowercase hexadecimal and non-zero identifiers before assuming the fault is downstream.
Reproduce a production trace by hand
Take a header from a real request and replay it against a staging endpoint to follow the same trace through. Build the request with the curl command builder and paste the header straight into it.
Explain trace context to a team
The field anatomy and trace-flags tables on this page are static reference material you can point at, and the preset chips demonstrate each failure mode without anyone having to break a service to produce one.

How the W3C Trace Context Validator Works

The four-field grammar
version "-" trace-id "-" parent-id "-" trace-flags, all lowercase hexadecimal. Version is 2 digits, trace-id 32, parent-id 16 and trace-flags 2 — 52 hex digits plus 3 dashes, 55 characters exactly for version 00. Uppercase hexadecimal makes the header invalid even though the value looks correct, and both an all-zero trace-id and an all-zero parent-id are explicitly invalid rather than empty.
trace-flags is a bit field
Bit 0 (mask 0x01) is sampled: set means the caller may have recorded trace data. Bit 1 (mask 0x02), introduced in Level 2, is random-trace-id: when set, at least the right-most 7 bytes of the trace-id must have been chosen randomly with uniform distribution, which lets downstream systems sample or shard on them. Bits 2 to 7 are reserved and must be ignored on receipt and cleared on outbound requests. Because reserved bits can be present, the field must be tested with a bitwise AND — an equality check against 0x01 misreports a sampled trace that also carries a reserved bit.
Forward compatibility with future versions
Version is 00 today and ff is forbidden, but a parser that rejects everything else is wrong. The specification asks receivers to attempt parsing when the version is higher and the header is at least as long as the known format, reading the fields they recognise and tolerating extra trailing data, rather than restarting the trace. This decoder follows that rule: a future version parses successfully and is flagged as a warning rather than an error.
tracestate limits that bite in production
At most 32 list-members — a hard grammatical bound, so a longer list makes the header invalid and receivers discard it. Each key is at most 256 characters and begins with a lowercase letter or digit; since Level 2 the @ is an ordinary key character rather than a tenant separator. Each value is 1 to 256 printable ASCII characters, never a comma or an equals sign. Duplicate keys are invalid, and empty list-members are explicitly allowed — a trailing comma left behind when an intermediary removes an entry is still a valid header. Separately, vendors should propagate at least 512 characters of the combined header; when they have to trim to stay inside that budget, entries longer than 128 characters should go first, which is why a verbose vendor's data disappears before a terse one's.

Trace Context Best Practices

Test flags with a bitwise AND
Write flags & 0x01 rather than flags == 0x01. Six of the eight bits are reserved for future use, and an equality check will start misreporting sampled traces the moment any of them appears in the wild.
Treat an all-zero ID as a broken pipeline
It is not an empty value to be tolerated. Reject the header, and go and find the component that failed to initialise its tracer or is injecting a placeholder.
Look upstream when the sampled bit is clear
Parent-based samplers propagate the caller's decision. If traces are missing, identify which service is sending you a parent span with sampling off before auditing your own configuration.
Keep tracestate short
The 32-member ceiling is a hard grammatical bound — exceed it and the header is invalid. Separately, only 512 characters of the combined header are guaranteed to propagate, and trimming drops entries over 128 characters first. Anything that must survive a long call chain does not belong in tracestate.
Never log a trace ID as a JavaScript number
A 128-bit trace ID and even a 64-bit Datadog identifier both exceed Number.MAX_SAFE_INTEGER. Keep them as strings, and convert with BigInt when you have to do arithmetic, or you will silently corrupt the last digits.

traceparent Decoder FAQ

What is the traceparent header?
It is the single HTTP header that carries a distributed trace across service boundaries, standardised by the W3C so that tools from different vendors can follow the same request. It holds four dash-separated fields — version, trace-id, parent-id and trace-flags — and for the current version it is always exactly 55 characters. Every major tracing system now speaks it, which is what makes a request traceable from an edge proxy through half a dozen services without every hop agreeing on a vendor. The full grammar is defined in the W3C Trace Context recommendation.
What does traceparent trace-flags 00 mean?
It means the caller explicitly decided this trace should not be recorded. The sampled bit is bit 0 of the trace-flags byte; when it is clear, an upstream sampler evaluated the request and chose against recording it. This is the single most misread value in the header, because it looks like a failure and is in fact a decision. If spans are missing, the useful question is not what is broken in your service but which upstream service is sending you a parent span with sampling turned off — a parent-based sampler will then propagate that choice to everything downstream.
What is the difference between trace-flags 01, 02 and 03?
trace-flags is an eight-bit field, so these values are combinations rather than an enumeration. 01 sets bit 0 only: the trace is sampled. 02 sets bit 1 only: the Level 2 random-trace-id flag, which asserts that at least the right-most seven bytes of the trace ID were generated with uniform randomness — downstream systems can then sample or shard on those bytes safely. 03 sets both. Because it is a bit field, you must test it with a bitwise AND; comparing the whole byte against 01 will misreport any trace that also carries a reserved bit, and reserved bits are exactly what future versions will start using.
Why is my trace ID all zeros?
Because tracing was never initialised, not because the trace exists but has no data. The specification lists an all-zero trace-id as an invalid value and instructs receivers to ignore the entire header, so nothing downstream will link to it. In practice it comes from an SDK that failed to start, a manually constructed header, or middleware inserting a placeholder when no real context was available. The all-zero parent-id, 0000000000000000, is invalid for the same reason.
How do I convert a W3C trace ID to a Datadog trace ID?
Take the lower 64 bits — the right-hand 16 hex digits — and render them as a decimal string; that is what goes in x-datadog-trace-id. The higher 64 bits stay hexadecimal and travel separately in the _dd.p.tid tag. The parent-id converts to decimal whole. Getting this backwards, or converting all 128 bits to one decimal number, produces an identifier that matches nothing in the UI, which is why it recurs across tracer issue trackers. This page performs the split for you; if you want to explore the underlying hexadecimal arithmetic on arbitrary values, the number base converter handles general base conversion, while this page stays specific to trace identifiers.
Does a traceparent contain a timestamp?
No — and this trips people up because some other trace identifiers do. A W3C trace-id is 16 opaque bytes with no embedded time. An AWS X-Ray trace ID, by contrast, is 1-{8 hex}-{24 hex} where the first eight hex digits are the creation time in epoch seconds, so converting between the two formats moves the bytes around but cannot invent a timestamp that was never there. If you need identifiers that do sort by time, that is what UUIDv7 and ULID are for.
Is the header I paste here uploaded anywhere?
No. Every field is parsed locally in your browser with plain string and BigInt arithmetic — there is no server call, no logging of what you type, and nothing retained. This matters more here than for most tools, because a traceparent taken from a production request identifies real traffic in your observability backend. You do not have to take our word for it: open your browser's developer tools, watch the Network panel stay silent while you type, or disconnect from the network entirely and keep decoding. The absence of any external request is also enforced by an automated contract test that runs on every build, so it cannot quietly regress.
Does this decoder work offline?
Yes. The page is static and the decoder is a few kilobytes of JavaScript with no dependencies, so once it has loaded you can go offline — or turn on airplane mode before you paste anything — and it keeps working exactly the same. If you are handling headers from a sensitive environment, that is the sequence worth using: load the page, disconnect, then paste. The Copy link button encodes state in the URL fragment after the # character, and fragments are never transmitted to a server either.

Related Tools

View all tools →