Claude Skills Guide

Chrome Extension GraphQL Network Inspector: A Developer Guide

GraphQL has transformed how developers build APIs, offering flexible queries and precise data fetching. However, debugging GraphQL requests in the browser requires specialized tools beyond standard network inspectors. This guide covers everything you need to know about Chrome extensions for inspecting GraphQL network traffic, from using existing tools to building your own inspector.

Why Standard DevTools Fall Short

The Chrome DevTools Network tab shows HTTP requests, but GraphQL operations are just POST requests with a JSON body. You cannot easily distinguish between queries, mutations, and subscriptions. Filtering by operation name requires manual searching through request payloads. This is where dedicated GraphQL network inspectors become essential.

A well-designed GraphQL network inspector extracts operation names, variables, and responses from requests, presenting them in a readable format. It should handle batched queries, persist operation history, and integrate smoothly with your development workflow.

Several extensions provide GraphQL-specific network inspection. The most widely used include Apollo Client DevTools, GraphQL Network Inspector, and responses from the broader Chrome Web Store ecosystem.

Apollo Client DevTools

If your application uses Apollo Client, the built-in DevTools extension provides operation-level inspection. Open Chrome DevTools and select the “Apollo” tab. You will see a list of executed operations with their names, variables, and cache state. The extension works automatically with Apollo Client applications and requires no configuration.

// When Apollo Client is present, operations appear automatically
// Query example that would appear in Apollo DevTools
const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
      posts {
        title
      }
    }
  }
`;

// Execute the query - it will appear in DevTools
const { data } = await client.query({
  query: GET_USER,
  variables: { id: "123" }
});

Standalone GraphQL Network Inspectors

For non-Apollo GraphQL implementations, standalone extensions like GraphQL Network Inspector intercept all requests containing GraphQL operation bodies. These tools display the complete request-response cycle with operation names extracted from the payload.

When selecting an extension, prioritize these features:

Building Your Own GraphQL Network Inspector

Creating a custom inspector gives you full control over functionality and integration. Here is a practical implementation using Chrome’s declarativeNetRequest API and background script architecture.

Project Structure

graphql-inspector/
├── manifest.json
├── background.js
├── inspector.js
└── popup/
    ├── popup.html
    └── popup.js

Manifest Configuration

{
  "manifest_version": 3,
  "name": "GraphQL Network Inspector",
  "version": "1.0",
  "permissions": [
    "declarativeNetRequest",
    "storage"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "host_permissions": [
    "<all_urls>"
  ]
}

Background Script for Request Interception

// background.js
const graphqlRequests = [];

chrome.webRequest.onBeforeRequest.addListener(
  (details) => {
    if (details.method === 'POST' && details.requestBody) {
      try {
        const body = JSON.parse(
          new TextDecoder().decode(details.requestBody.binary[0])
        );
        
        if (body.query) {
          const request = {
            id: Date.now(),
            url: details.url,
            operationName: body.operationName || extractOperationName(body.query),
            variables: body.variables || {},
            query: body.query,
            timestamp: new Date().toISOString()
          };
          
          graphqlRequests.push(request);
          
          // Keep only last 100 requests
          if (graphqlRequests.length > 100) {
            graphqlRequests.shift();
          }
          
          // Store for popup access
          chrome.storage.local.set({ graphqlRequests });
        }
      } catch (e) {
        // Not a GraphQL request
      }
    }
  },
  { urls: ["<all_urls>"] },
  ["requestBody"]
);

// Extract operation name from query document
function extractOperationName(query) {
  const match = query.match(/(?:query|mutation|subscription)\s+(\w+)/);
  return match ? match[1] : 'Anonymous';
}

Content Script for DOM Injection

// inspector.js - injected into web pages
class GraphQLInspector {
  constructor() {
    this.requests = [];
    this.setupMutationObserver();
  }

  setupMutationObserver() {
    // Monitor network requests via fetch/XHR interception
    const originalFetch = window.fetch;
    window.fetch = async (...args) => {
      const response = await originalFetch.apply(this, args);
      
      if (this.isGraphQL(args)) {
        this.captureRequest(args, response.clone());
      }
      
      return response;
    };
  }

  isGraphQL(args) {
    const [resource] = args;
    const url = resource instanceof Request ? resource.url : resource;
    const options = args[1] || {};
    
    return options.body && 
           typeof options.body === 'string' && 
           options.body.includes('query');
  }

  async captureRequest(args, response) {
    try {
      const body = await response.json();
      const request = {
        operationName: body.operationName || 'Anonymous',
        variables: body.variables,
        response: body.data,
        errors: body.errors
      };
      
      this.requests.push(request);
      this.notifyPanel(request);
    } catch (e) {
      // Response not JSON
    }
  }

  notifyPanel(request) {
    chrome.runtime.sendMessage({
      type: 'GRAPHQL_REQUEST',
      payload: request
    });
  }
}

// Initialize when DOM is ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => new GraphQLInspector());
} else {
  new GraphQLInspector();
}
<!-- popup/popup.html -->
<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 400px; font-family: system-ui; }
    .request { padding: 8px; border-bottom: 1px solid #eee; }
    .request:hover { background: #f5f5f5; }
    .operation-name { font-weight: bold; }
    .timestamp { color: #666; font-size: 12px; }
  </style>
</head>
<body>
  <h3>GraphQL Requests</h3>
  <div id="requests"></div>
  <script src="popup.js"></script>
</body>
</html>
// popup/popup.js
chrome.storage.local.get('graphqlRequests', (data) => {
  const container = document.getElementById('requests');
  const requests = data.graphqlRequests || [];
  
  requests.slice(-10).reverse().forEach(req => {
    const div = document.createElement('div');
    div.className = 'request';
    div.innerHTML = `
      <div class="operation-name">${req.operationName}</div>
      <div class="timestamp">${new Date(req.timestamp).toLocaleTimeString()}</div>
    `;
    container.appendChild(div);
  });
});

Advanced Features to Consider

Once you have basic inspection working, these advanced features improve developer experience significantly.

Query Formatting

Pretty-print GraphQL queries for readability using a library like graphql/language/printer:

import { print } from 'graphql';

// Format raw query for display
const formattedQuery = print(parsedQuery);

Error Highlighting

GraphQL responses may include errors array. Display these prominently with context:

if (response.errors) {
  response.errors.forEach(error => {
    console.error(`[GraphQL Error] ${error.message}`);
  });
}

Request Search and Filter

Implement filtering by operation name or variables:

function filterRequests(requests, searchTerm) {
  return requests.filter(req => 
    req.operationName.toLowerCase().includes(searchTerm.toLowerCase()) ||
    JSON.stringify(req.variables).includes(searchTerm)
  );
}

Integration Tips

For maximum effectiveness, position your inspector alongside other development tools. Most developers keep DevTools open on the right panel while working in the main editor. Place your GraphQL inspector popup in a consistent location and use keyboard shortcuts for quick access.

If building for a team, consider adding authentication context to requests so you can filter by logged-in user. This helps when debugging multi-tenant applications where different users see different data.

Conclusion

Chrome extensions for GraphQL network inspection bridge the gap between standard browser DevTools and the specific needs of GraphQL debugging. Whether you use existing tools like Apollo Client DevTools or build a custom solution, proper inspection capabilities dramatically accelerate development and troubleshooting.

The implementation above provides a foundation. Extend it based on your specific GraphQL setup, whether you work with Apollo, URQL, or vanilla GraphQL clients.

Built by theluckystrike — More at zovo.one