---
title: Network Inspection
description: 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 case | Package |
| -------- | ------- |
| Dio | `xray_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

```dart
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

<Info>Available since 0.0.9</Info>

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.

```dart
import 'package:xray_inspector/xray_inspector.dart';

final networkInspector = XRayNetworkInspector(enableHttpOverride: true);
```

<Warning>
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.
</Warning>

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

<Info>
`enableHttpOverride` is silently ignored on web — `dart:io` is not available there.
</Info>

## Accessing captured calls

```dart
// 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:

```dart
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

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

## Clearing calls

```dart
networkInspector.clear();
```

## Custom inspector title

```dart
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:

| Field                | Type                    | Description                       |
| -------------------- | ----------------------- | --------------------------------- |
| `id`                 | `String`                | Unique ID (timestamp-based)       |
| `method`             | `String`                | HTTP method (`GET`, `POST`, etc.) |
| `uri`                | `String`                | Full request URI                  |
| `requestHeaders`     | `Map<String, dynamic>?` | Request headers                   |
| `requestBody`        | `dynamic`               | Request body                      |
| `responseStatusCode` | `int?`                  | HTTP status code                  |
| `responseHeaders`    | `Map<String, dynamic>?` | Response headers                  |
| `responseBody`       | `dynamic`               | Response body                     |
| `status`             | `XRayNetworkCallStatus` | `loading` / `success` / `error`   |
| `startTime`          | `DateTime`              | When the request started          |
| `endTime`            | `DateTime?`             | When the request completed        |
| `durationMs`         | `int?`                  | Duration in milliseconds          |
| `error`              | `String?`               | 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:

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

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

<Info>
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.
</Info>
