Network Inspection

Capture and inspect HTTP network calls from Dio or any dart:io HttpClient.

The network inspector captures every HTTP request, response, and error made through your HTTP client, storing them in memory for real-time inspection.

Packages

Use casePackage
Dioxray_network_dio_interceptor
All dart:io clients (Dio, package:http, and any other client that delegates to dart:io)xray_inspector (enableHttpOverride)

Setup with Dio

import 'package:xray_inspector/xray_inspector.dart';
import 'package:xray_network_dio_interceptor/xray_network_dio_interceptor.dart';
import 'package:dio/dio.dart';

final networkInspector = XRayNetworkInspector();

final dio = Dio()
  ..interceptors.add(
    XRayNetworkDioInterceptor(inspector: networkInspector),
  );

Setup with global HTTP override

Available since 0.0.9

Pass enableHttpOverride: true to intercept every HTTP request made in the app at the dart:io level — Dio, package:http, and any other client that uses dart:io under the hood. No changes to individual clients are needed.

import 'package:xray_inspector/xray_inspector.dart';

final networkInspector = XRayNetworkInspector(enableHttpOverride: true);

The HTTP override captures all traffic in the process, regardless of which HTTP client made the call. If you also use a Dio interceptor, Dio calls will appear in both inspectors — the Dio inspector and the HTTP override inspector.

Only one XRayNetworkInspector can have enableHttpOverride: true at a time. Enabling it on a second inspector throws a StateError at startup.

enableHttpOverride is silently ignored on web — dart:io is not available there.

Accessing captured calls

// All captured calls (snapshot)
final calls = networkInspector.calls;

// Reactive — rebuilds your widget when calls change
ValueListenableBuilder<List<XRayNetworkCall>>(
  valueListenable: networkInspector.callsNotifier,
  builder: (context, calls, _) {
    return Text('${calls.length} calls captured');
  },
);

Listening to new calls in code

Implement XRayNetworkInterceptorListener and register it:

class MyListener implements XRayNetworkInterceptorListener {
  @override
  void onNetworkCallAdded(XRayNetworkCall call) {
    debugPrint('[Network] ${call.method} ${call.uri}${call.responseStatusCode}');
  }
}

final listener = MyListener();
networkInspector.addListener(listener);

// Clean up when done
networkInspector.removeListener(listener);

Finding a call by ID

final call = networkInspector.findById('some-call-id');

Clearing calls

networkInspector.clear();

Custom inspector title

final networkInspector = XRayNetworkInspector(title: 'API Calls');

The title is displayed in the remote UI and used to generate the inspector's ID.

Network call model

Each captured call is an XRayNetworkCall with these fields:

FieldTypeDescription
idStringUnique ID (timestamp-based)
methodStringHTTP method (GET, POST, etc.)
uriStringFull request URI
requestHeadersMap<String, dynamic>?Request headers
requestBodydynamicRequest body
responseStatusCodeint?HTTP status code
responseHeadersMap<String, dynamic>?Response headers
responseBodydynamicResponse body
statusXRayNetworkCallStatusloading / success / error
startTimeDateTimeWhen the request started
endTimeDateTime?When the request completed
durationMsint?Duration in milliseconds
errorString?Error message if failed

Multiple network inspectors

You can run multiple network inspectors simultaneously. Each must have a distinct title (used to generate the inspector's ID). A common pattern is one inspector for Dio and one for all other HTTP traffic:

final networkDioInspector = XRayNetworkInspector(title: 'Network (Dio)');
final networkHttpInspector = XRayNetworkInspector(
  title: 'Network (Http)',
  enableHttpOverride: true,
);

final dio = Dio()
  ..interceptors.add(XRayNetworkDioInterceptor(inspector: networkDioInspector));

In this setup, Dio calls will appear in both inspectors — the Dio interceptor captures them with richer metadata, while the HTTP override captures them at the lower dart:io level.