Safeguard
Developer Tools•

The traceparent header explained, field by field

Break down the W3C traceparent header: version, trace ID, parent ID and flags, plus what your service should do when the header is missing or invalid.

Safeguard Security Team
3 min read

The traceparent header carries four dash separated fields: a version, a 32 character trace ID, a 16 character parent ID and a flags byte. Every service in a request path forwards the trace ID and replaces the parent ID with its own span, so traces connect across services.

An example

traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

Reading left to right, as defined in the W3C Trace Context specification:

  • version: two lowercase hex characters. The current version is 00, and ff is forbidden.
  • trace-id: 32 lowercase hex characters, 16 bytes, identifying the whole trace. All zeros is invalid.
  • parent-id: 16 lowercase hex characters, 8 bytes, identifying the calling operation. All zeros is invalid.
  • trace-flags: two hex characters. Only the lowest bit, sampled, is defined. It says the caller may have recorded trace data.

What your service does on receipt

When a request arrives with a valid header:

  1. Keep the trace ID.
  2. Create a new span for your own work, with the incoming parent ID as its parent.
  3. On each outgoing request, send the same trace ID with the parent ID set to your current operation.

The specification says not to change anything else in traceparent on the way out, apart from optionally updating the sampled flag, which requires a new parent ID.

When the header is missing, create a new trace ID and parent ID and start a new trace. When it is present but malformed, the specification says to ignore it and begin a fresh trace.

What tracestate is for

A second header, tracestate, carries vendor specific data as a comma separated list of key=value pairs, up to 32 entries. Each tracing system updates its own entry and puts it on the left. If tracestate arrives without traceparent, the specification says it is invalid and must be discarded. If traceparent cannot be parsed, tracestate must not be parsed either.

For most applications you do not write this logic yourself. A tracing library handles it. You still need to know it for two reasons.

Why this matters for debugging

First, any hop that does not forward the header splits your trace in two. Message queues, background workers and custom HTTP clients are the usual culprits. If a trace ends abruptly at one service, look at how that service makes outbound calls.

Second, the sampled flag is a hint about recording, not a guarantee. Different services may apply their own sampling rules, so a trace can be partial. Log the trace ID anyway so log search still works when the trace itself was dropped.

A safety note

Headers come from outside your trust boundary. Cap their length, validate the format before logging them, and do not put secrets or personal data in tracestate, because it is passed to every downstream service.

Quick check

Does a trace ID have to be random?

It must be unique enough that two traces do not collide. Use the generator in your tracing library instead of inventing one.

Is the sampled flag the same as keeping the data?

No. It tells downstream services that the caller may have recorded the trace. Whether data is stored depends on each system's sampling choices.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.