react-native-api-inspector
v1.0.0
Published
API inspector for React Native, Expo, React & Next.js by iamnsharma — auto-logs Axios/Fetch with masking, presets & floating UI. https://iamnsharma.useaifast.com
Maintainers
Readme
react-native-api-inspector
Lightweight API inspector for React Native, Expo, React, and Next.js.
Automatically logs Axios and Fetch requests with masking, presets, duplicate detection, slow-API warnings, cURL export, and optional floating UI.
Compatible with React 19 and React Native 0.86+.
Author: Aman Sharma (iamnsharma) · Portfolio · npm: iamnsharma45
- npm: https://www.npmjs.com/package/react-native-api-inspector
- Source / Issues / PRs: https://github.com/iamnsharma/react-native-api-inspector
- Bug reports: https://github.com/iamnsharma/react-native-api-inspector/issues
- Portfolio: https://iamnsharma.useaifast.com/
- Changelog: CHANGELOG.md
npm install react-native-api-inspector
# or
yarn add react-native-api-inspector
# or
pnpm add react-native-api-inspectorTable of contents
- Install
- React Native / Expo integration
- Axios integration
- React / Next.js integration
- initInspector config reference
- FloatingInspector props
- InspectorPanel props
- API reference
- Log entry types
- Example log output
- Testing against a local backend
- Troubleshooting
- Features
- License & publish
Package overview
| Import path | Exports |
| --- | --- |
| react-native-api-inspector | initInspector, attachAxiosInspector, attachFetchInspector, store helpers |
| react-native-api-inspector/react-native | FloatingInspector (React Native / Expo bubble UI) |
| react-native-api-inspector/react | InspectorPanel (React / Next.js web panel) |
Peer dependencies (all optional — install what you use):
| Peer | Version | When needed |
| --- | --- | --- |
| react | >= 17 | UI components |
| react-native | >= 0.68 | FloatingInspector |
| react-dom | >= 17 | InspectorPanel |
| axios | >= 0.21 \|\| >= 1.0 | Axios interceptor only |
1. Install
npm install react-native-api-inspector
# or
yarn add react-native-api-inspector
# or
pnpm add react-native-api-inspectorIf you use Axios:
yarn add axios2. React Native / Expo integration
Step 1 — Create a dev-only host component
// src/devtools/ApiInspectorHost.tsx
import React, { useEffect } from "react";
import {
initInspector,
attachFetchInspector,
} from "react-native-api-inspector";
import { FloatingInspector } from "react-native-api-inspector/react-native";
export function ApiInspectorHost() {
useEffect(() => {
if (!__DEV__) return;
initInspector({
enabled: true,
preset: "pretty",
slowThresholdMs: 1500,
detectDuplicates: true,
mask: true,
visibility: {
showHeaders: false,
showPayload: true,
showParams: true,
showTimestamp: true,
},
colors: {
request: "#00BFFF",
success: "#22c55e",
error: "#ef4444",
warning: "#f59e0b",
},
});
const detach = attachFetchInspector();
return () => detach();
}, []);
if (!__DEV__) return null;
return (
<FloatingInspector
position="bottom-right"
accentColor="#0284c7"
/>
);
}Step 2 — Mount in App root
Mount inside your root providers (e.g. SafeAreaProvider / navigation):
import { ApiInspectorHost } from "./src/devtools/ApiInspectorHost";
export default function App() {
return (
<>
{/* your app */}
{__DEV__ ? <ApiInspectorHost /> : null}
</>
);
}Step 3 — Automatic logging
All fetch() calls are logged after attachFetchInspector().
Step 4 — Optional smoke test
async function testInspector() {
await fetch("https://jsonplaceholder.typicode.com/posts/1");
await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "test", body: "hello", userId: 1 }),
});
await fetch("https://jsonplaceholder.typicode.com/posts/99999"); // 404
}Step 5 — Verify
- Metro / Xcode / Android Studio console shows REQUEST / SUCCESS / ERROR blocks
- Floating API bubble appears bottom-right
- Tap bubble → search, export JSON, clear logs
- Sensitive fields (
password,token,authorization) are masked as***
Important: Only enable in
__DEV__. Never ship the floating UI in production builds.
3. Axios integration
import axios from "axios";
import { initInspector, attachAxiosInspector } from "react-native-api-inspector";
const api = axios.create({ baseURL: "https://api.example.com" });
initInspector({ enabled: __DEV__, preset: "pretty" });
attachAxiosInspector(api);
await api.get("/users");Notes:
attachAxiosInspector(instance)returns a detach function- Safe to call once per Axios instance
- Call
initInspector()before attaching interceptors - The default
axiosexport is not auto-patched — pass youraxios.create()instance
4. React / Next.js integration
"use client";
import { useEffect } from "react";
import { initInspector, attachFetchInspector } from "react-native-api-inspector";
import { InspectorPanel } from "react-native-api-inspector/react";
export function ApiDebug() {
useEffect(() => {
initInspector({ enabled: process.env.NODE_ENV === "development" });
return attachFetchInspector();
}, []);
if (process.env.NODE_ENV === "production") return null;
return <InspectorPanel position="bottom-right" />;
}Mount <ApiDebug /> in your app layout or root component.
Next.js App Router: keep this in a client component. Server Component / Route Handler
fetchis separate — usetrackRequest/trackSuccess/trackErrormanually if needed.
5. initInspector config reference
Top-level options
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| enabled | boolean | __DEV__ / NODE_ENV !== "production" | Master enable switch |
| preset | "minimal" \| "compact" \| "pretty" \| "verbose" | "pretty" | Log format preset |
| theme | "dark" \| "light" \| "auto" | "dark" | Console color theme |
| collapseAfter | number | 50 | Truncate long strings after N characters |
| slowThresholdMs | number | 3000 | Flag slow requests (ms) |
| detectDuplicates | boolean | true | Detect duplicate in-flight requests |
| showCurl | boolean | false | Print cURL for each request |
| mask | boolean \| MaskConfig | true | Sensitive field masking |
| layout | LayoutConfig | see below | Box borders / spacing |
| colors | ColorConfig | see below | Hex colors |
| visibility | VisibilityConfig | see below | Field toggles |
| filter | FilterConfig | — | Include / exclude / search |
| hooks | InspectorHooks | — | Lifecycle callbacks |
| formatter | (entry, formatted) => string | — | Override formatted output |
| logger | { log?, warn?, error? } | console.* | Custom log sink |
Zero-config: initInspector() with no arguments enables in development, uses the pretty preset, and masks common sensitive fields.
layout (LayoutConfig)
| Property | Type | Description |
| --- | --- | --- |
| border | boolean | Draw a box border around each log block |
| borderStyle | "single" \| "double" \| "round" \| "none" | Border character style |
| padding | number | Inner padding (spaces) |
| spacingBefore | number | Blank lines before each log |
| spacingAfter | number | Blank lines after each log |
colors (ColorConfig)
| Property | Type | Description |
| --- | --- | --- |
| request | string | Hex color for request logs |
| success | string | Hex color for success logs |
| error | string | Hex color for error logs |
| warning | string | Hex color for warnings |
| muted | string | Muted text color |
| label | string | Label text color |
visibility (VisibilityConfig)
| Property | Type |
| --- | --- |
| showHeaders | boolean |
| showPayload | boolean |
| showParams | boolean |
| showTimestamp | boolean |
| showRequestId | boolean |
| showDuration | boolean |
| showResponseSize | boolean |
| showCurl | boolean |
mask (MaskConfig when object)
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| fields | string[] | password, token, authorization, … | Field names to mask (case-insensitive) |
| maskWith | string | "***" | Replacement string |
| maskHeaders | boolean | true | Also mask Authorization header values |
filter (FilterConfig)
| Property | Type | Description |
| --- | --- | --- |
| include | (string \| RegExp)[] | Only log URLs matching these patterns |
| exclude | (string \| RegExp)[] | Skip URLs matching these patterns |
| methods | string[] | HTTP methods to include (e.g. ["GET","POST"]); empty = all |
| errorStatusThreshold | number | Minimum status to log as error (default 400) |
| search | string | Free-text search against URL/body at log time |
hooks (InspectorHooks)
onRequest?: (entry: RequestLogEntry) => void | RequestLogEntry;
onSuccess?: (entry: SuccessLogEntry) => void | SuccessLogEntry;
onError?: (entry: ErrorLogEntry) => void | ErrorLogEntry;Full example
initInspector({
enabled: true,
preset: "pretty",
theme: "dark",
collapseAfter: 50,
slowThresholdMs: 3000,
detectDuplicates: true,
showCurl: false,
layout: {
border: true,
borderStyle: "double",
padding: 1,
spacingBefore: 2,
spacingAfter: 2,
},
colors: {
request: "#00BFFF",
success: "#22c55e",
error: "#ef4444",
warning: "#f59e0b",
},
visibility: {
showHeaders: false,
showPayload: true,
showParams: true,
showTimestamp: true,
},
mask: {
fields: ["password", "token", "authorization"],
maskWith: "***",
maskHeaders: true,
},
filter: {
exclude: ["/health", /analytics/],
methods: ["GET", "POST"],
search: "users",
},
hooks: {
onRequest: (entry) => entry,
onSuccess: (entry) => entry,
onError: (entry) => entry,
},
formatter: (entry, formatted) => formatted,
});6. FloatingInspector props
import { FloatingInspector } from "react-native-api-inspector/react-native";| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| initiallyOpen | boolean | false | Start with modal panel open |
| position | "bottom-right" \| "bottom-left" \| "top-right" \| "top-left" | "bottom-right" | Floating bubble position |
| accentColor | string | "#00BFFF" | Bubble and close button accent |
| onExport | (json: string) => void | native Share sheet | Custom export handler |
UI features: live log list, search/filter, tap row for full JSON detail, Export, Clear, error count badge on the bubble.
7. InspectorPanel props
import { InspectorPanel } from "react-native-api-inspector/react";| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| position | "bottom-right" \| "bottom-left" | "bottom-right" | Panel dock position |
| defaultOpen | boolean | false | Start with panel expanded |
| maxHeight | number | 420 | Max panel height in pixels |
| className | string | — | Root CSS class name |
| style | CSSProperties | — | Inline style overrides |
8. API reference
| Export | Description |
| --- | --- |
| initInspector(config?) | Configure and enable the inspector |
| getInspectorConfig() | Read the resolved config object |
| attachAxiosInspector(instance, options?) | Attach Axios interceptors; returns detach fn |
| attachFetchInspector(options?) | Patch global fetch; returns detach fn |
| isFetchInspectorAttached() | Whether fetch interceptor is active |
| copyCurl(options) | Build a cURL command string |
| exportLogsJSON() | Export all in-memory logs as JSON |
| clearInspectorLogs() | Clear the in-memory log store |
| getInspectorStore() | Access store helpers |
| setInspectorEnabled(bool) | Toggle without resetting config |
| setInspectorFilter(filter) | Update runtime search/filter |
| FloatingInspector | RN floating UI — from /react-native |
| InspectorPanel | Web panel — from /react |
attachFetchInspector options
target?: typeof globalThis & { fetch: typeof fetch };Custom fetch host (default globalThis); useful in tests.
attachAxiosInspector options
once?: boolean; // only attach if not already attached (default true)getInspectorStore() methods
| Method | Description |
| --- | --- |
| logs | All logged entries |
| clear() | Clear logs |
| exportJSON() | Same as exportLogsJSON() |
| getById(id) | Entries matching request ID |
| filter(predicate) | Filter entries |
| subscribe(listener) | Live listener; returns unsubscribe |
9. Log entry types
LogEntry is a union of:
RequestLogEntry (type: "request")
id, method, baseURL, url, fullURL, headers, params, data, timestamp, startedAt, optional curl, isDuplicate
SuccessLogEntry (type: "success")
id, method, fullURL, status, statusText, duration, responseSize, responsePreview, headers, timestamp, optional isSlow
ErrorLogEntry (type: "error")
id, method, fullURL, status, statusText, message, errorResponse, duration, timestamp, optional isSlow
10. Example log output
REQUEST
╔══════════════════════════════════════╗
║ 🚀 REQUEST ║
║ Method GET ║
║ Base URL https://api.example.com║
║ Endpoint /users?page=1 ║
║ Full URL https://api.example.com/users?page=1
║ Request ID req_… ║
║ Timestamp 2026-08-04 20:15:01.123║
║ Params { "page": "1" } ║
║ Payload (empty) ║
╚══════════════════════════════════════╝SUCCESS
╔══════════════════════════════════════╗
║ ✅ SUCCESS ║
║ Status 200 OK ║
║ Duration 142ms ║
║ Size 1.2 KB ║
║ Response { "users": […] } ║
╚══════════════════════════════════════╝ERROR
╔══════════════════════════════════════╗
║ ❌ ERROR ║
║ Status 500 ║
║ Message Request failed … ║
║ Duration 890ms ║
║ Error Body { "error": "…" } ║
╚══════════════════════════════════════╝11. Testing against a local backend
| Environment | Base URL for fetch |
| --- | --- |
| iOS Simulator | http://localhost:3000/api/v1 |
| Android Emulator | http://10.0.2.2:3000/api/v1 |
| Physical device | http://<YOUR_MAC_LAN_IP>:3000/api/v1 |
Example (Android emulator → local NestJS / Express API):
await fetch("http://10.0.2.2:3000/api/v1/health");
await fetch("http://10.0.2.2:3000/api/v1/auth/otp/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phone: "+919876543210", otp: "123456" }),
});Tokens and passwords in request bodies appear masked as *** in logs.
12. Troubleshooting
Cannot read property 'ReactCurrentDispatcher' of undefined
Cause: Duplicate React instance, or react/jsx-runtime bundled inside package dist.
Fix (consumers): Ensure a single copy of react:
yarn why react
# or
npm ls reactFix (maintainers): Externalize react, react/jsx-runtime, react/jsx-dev-runtime, and react-native in Rollup for UI packages, then rebuild.
Inspector not showing any logs
- Call
initInspector({ enabled: true })beforeattachFetchInspector()/attachAxiosInspector() - Confirm
__DEV__is true (or setenabled: trueexplicitly) - Check
filter.excludeis not blocking your URLs - On Android emulator, use
10.0.2.2instead oflocalhost
FloatingInspector not visible
- Mount in App root, not inside a screen that unmounts
- Wrap with
{__DEV__ && <FloatingInspector />} - Check
positionis not off-screen
Missing in release builds
Expected — never ship inspector UI in production.
Axios logs missing
- Call
attachAxiosInspector(yourAxiosInstance)on the same instance used for requests - Default
axiosexport is not auto-patched
13. Features
| Feature | Support |
| --- | --- |
| TypeScript | ✅ |
| Axios interceptors | ✅ |
| Fetch interceptors | ✅ |
| React Native / Expo | ✅ |
| React / Next.js | ✅ |
| Zero-config setup | ✅ |
| Tree-shakable (ESM + CJS) | ✅ |
| Presets (minimal, compact, pretty, verbose) | ✅ |
| Sensitive field masking | ✅ |
| Copy as cURL | ✅ |
| Duplicate request detection | ✅ |
| Slow API warning | ✅ |
| Search / filtering | ✅ |
| Floating RN + web UI | ✅ |
| Export logs as JSON | ✅ |
| Hooks (onRequest, onSuccess, onError) | ✅ |
| React 19 compatible | ✅ |
14. License & community
License: MIT
Maintained by Aman Sharma (iamnsharma) — iamnsharma45 on npm · Portfolio · useaifast.com
| Resource | Link | | --- | --- | | Issues | https://github.com/iamnsharma/react-native-api-inspector/issues | | Discussions | https://github.com/iamnsharma/react-native-api-inspector/discussions | | Author (GitHub) | https://github.com/iamnsharma | | Author (npm) | https://www.npmjs.com/~iamnsharma45 | | Portfolio | https://iamnsharma.useaifast.com/ | | Website | https://useaifast.com | | Contributing | CONTRIBUTING.md | | Security | SECURITY.md | | Code of Conduct | CODE_OF_CONDUCT.md | | Changelog | CHANGELOG.md |
Maintainers — publish checklist
pnpm install
pnpm build
pnpm test
pnpm lint
cd packages/react-native-api-inspector
npm publish --access publicRequires Node ≥ 18 and pnpm ≥ 8.
Monorepo structure (contributors)
packages/
core/ # Engine: formatting, masking, store, hooks
axios/ # Axios interceptor
fetch/ # Fetch interceptor
react-native-ui/ # FloatingInspector
react-ui/ # InspectorPanel
react-native-api-inspector/ # Public npm package (bundles the above)The published react-native-api-inspector package is self-contained — consumers only run npm install react-native-api-inspector.
Appendix — Advanced: local monorepo linking
For contributing to this repo from a host React Native app before publishing:
- Build the monorepo:
pnpm build - Point Metro
watchFolders/extraNodeModulesatpackages/* - Prefer
npm install react-native-api-inspectorfrom npm once published
Local Metro path linking is only needed for package development — not for normal installs.
