interceptOutbound: true (the default), ApiTraffic records the calls your application makes
out to other APIs and correlates each one with the inbound request that caused it, so a request
in the dashboard shows its downstream calls with their own timing, headers and payloads.
Capture is read-only by design: your outbound call is issued exactly as your code wrote it, and
payloads are read from copies. If anything about capture fails, the call still goes through — you
lose the record, never the request.
What is captured
Two hooks cover the two ways Node.js makes an HTTP call:
Both hooks produce the same record shape, so an
axios call and a fetch call to the same
service look the same in the dashboard.
Global
fetch does not go through http.request — it drives Node’s built-in undici client
straight onto a socket. That is why it has a separate hook, and why anything using fetch needs
a client version that includes it. Requires Node 18 or later.When a body is not captured
A record can arrive with the body marked as not captured. This is deliberate, not a failure, and happens when reading the payload would mean interfering with your call or holding a large amount of data in memory:- The payload is over the size cap. Bodies are capped per call (
maxFetchBodyLengthforfetch, 512 KB by default;API_TRAFFIC_MAX_FETCH_BODY_LENGTHto change it). Oversized payloads are stored truncated, or skipped when the server declares a length above the cap up front. - The payload is not text. Binary content types (images, archives,
application/octet-stream) are recorded as metadata only. Server-sent event streams (text/event-stream) are captured up to the size cap onhttp/httpscalls, and recorded as metadata only onfetch, where reading a copy of a stream would keep it running after your code cancels it. - The request body is a stream,
FormDataorBlob. Reading it would consume the body your call is about to send, so it is left untouched.
When an outbound call is not captured at all
interceptOutboundis off, orcaptureFetch/API_TRAFFIC_CAPTURE_FETCHis off forfetchspecifically.- Calls made before ApiTraffic is set up. The hooks are installed during setup, so a call issued at import time, before the middleware or plugin is registered, is not seen.
- Something else replaced
globalThis.fetchafter setup. Instrumentation and mocking libraries normally wrapfetch, which is fine — ApiTraffic’s hook keeps working underneath, and installing it twice never stacks wrappers. But a library that assigns a brand new function toglobalThis.fetch(some HTTP mocking and polyfill packages do this) removes ApiTraffic’s hook, and those calls are not recorded. Iffetchcalls are missing from your requests, check the order of your setup: ApiTraffic should be initialised after any library that replacesfetchwholesale. - Calls to ApiTraffic itself are excluded, so reporting traffic never shows up as your application’s outbound traffic.
- The call goes through a client that bypasses both hooks, such as
undici.requestor aPool. With APM installed these still appear on the request timeline, with timing and metadata but no bodies.
Redaction and exclusions
Outbound records go through the same redaction and exclusion rules as inbound traffic, so credentials in an outboundAuthorization header or a payload field are masked by the same policy.