The Network Tab
See every HTTP request your app makes — to Supabase, to any API, to any server. The answer to 'why isn't my data loading?' lives here.
Every time your app needs data — to load a list of jobs, to save a form, to check if a user is logged in — it makes an HTTP request to a server. The Network tab shows you every single one of those requests, what was sent, what came back, and whether it succeeded or failed.
If your app's data isn't loading, the answer is almost always visible in the Network tab within 30 seconds.
Why First: The Data That Won't Load
You built a dashboard that should show your CA firm's client list. You log in, navigate to the dashboard, and the list is empty. No error message. Just empty. You have no idea if the problem is in your React component, your Supabase query, or the database itself.
Open the Network tab.
Find the request to Supabase for your client list. Click it. Look at the Response. You will see one of these:
- A JSON array of clients — the data IS coming back. The problem is in your React component (how it's rendering).
- An empty array — the query succeeded but returned nothing. Check your RLS policy or your
whereclause. - A 403 error response — RLS is blocking the query. The user doesn't have permission.
- A 401 error — the user isn't authenticated. Token expired or never sent.
- A 500 error — something crashed on the server side.
Each of these is a completely different problem with a completely different solution. The Network tab tells you which one you're dealing with. Without it, you are guessing.
The Excel Analogy
Think of the Network tab like a detailed log of every VLOOKUP your workbook runs against an external data source — with timestamps, what query was sent, what data came back, and whether the lookup succeeded or failed.
In Excel, when a data connection fails, Excel might just show an error in the cell or refresh silently with no data. The Network tab is like having a panel that shows every connection attempt, the exact query sent, the exact response received, and the response code (success / not found / blocked / server error).
If your VLOOKUP is returning blank, you'd want to see: Did it reach the external sheet? Did the sheet return data? Did it return the right data? That is exactly what the Network tab tells you about API calls.
Opening the Network Tab and What You See
Click the Network tab in DevTools. If no requests are visible, refresh the page (F5 or Ctrl + R) — the Network tab only captures requests made while it is open.
You will see a list of rows, each representing one HTTP request. The columns are:
| Column | What It Shows |
|---|---|
| Name | The URL path (e.g., /rest/v1/jobs?select=*) |
| Method | GET (fetch data), POST (create), PATCH (update), DELETE |
| Status | The HTTP response code — 200 = success, red numbers = problems |
| Type | What kind of request — fetch, xhr, document, image, script |
| Size | How much data was transferred |
| Time | How long the request took (in milliseconds) |
The rows with red status codes are the ones to investigate first.
Filtering to Find Your Supabase Calls
Your app makes dozens of requests when it loads — HTML, CSS, JavaScript files, images, fonts. When you are looking for your API calls to Supabase, you do not want to wade through all of that.
Use the filter tabs at the top of the Network panel:
- Click Fetch/XHR — this shows only data requests (your Supabase calls, your API calls). Everything else disappears.
You can also use the filter text field. Type supabase or the table name (e.g., jobs) and only matching requests will appear.
Quick identification: Your Supabase requests will have URLs starting with your Supabase project URL, followed by /rest/v1/ (database queries) or /functions/v1/ (edge functions). Example: https://abcdef.supabase.co/rest/v1/jobs?select=*
Clicking a Request: The Four Important Panels
When you click on any request row, a panel opens on the right (or bottom) with details. There are four tabs you need to know:
What was sent and what came back at the metadata level.
This panel is split into two sections:
Request Headers — what your app sent to the server:
Authorization: Bearer eyJ...— your user's authentication token (check this exists when debugging 401 errors)Content-Type: application/json— tells the server you're sending JSONapikey: eyJ...— your Supabase anon key
Response Headers — what the server sent back:
content-type: application/json— confirming the response is JSON- Status line at the top shows the HTTP status code
When to check Headers: When you get a 401 (Unauthorized) — check if the Authorization header is present and has a valid token. If it's missing, your app isn't attaching the auth token to the request.
The Status Codes: What Each Color Means
Status codes are the server's way of telling your app what happened. Green numbers (2xx) mean success. Red numbers mean problems.
200 OK
Success. The request worked and the server returned data. If your app still shows no data after a 200, the problem is in your React component, not the API.
201 Created
Success — the record was created. This is the expected response when you INSERT into Supabase.
401 Unauthorized
Not authenticated. Either the user isn't logged in, or their auth token has expired. Check if the Authorization header is present in the Headers tab.
403 Forbidden
Authenticated but not allowed. The user is logged in but an RLS policy is blocking this specific query. Check your Supabase RLS policies for this table.
404 Not Found
The URL is wrong. The server doesn't recognize the endpoint you're calling. Check your Supabase URL and the table name in the query.
500 Internal Server Error
Something crashed on the server. Check the Response tab for the error message. Often a bad SQL query, missing required field, or edge function crash.
The 401 vs 403 distinction is critical. Both look like "permission denied" but they mean completely different things:
- 401 = "I don't know who you are." Fix: ensure the user is logged in and the auth token is attached to the request.
- 403 = "I know who you are, but you're not allowed to do this." Fix: check the RLS policy on the table.
Fixing a 401 by adjusting your RLS policy (or vice versa) will waste an hour of your time.
Checking Request Timing
The Time column tells you how long each request took in milliseconds. If your app feels slow, looking at request timing tells you where the time is going.
Click the Timing tab (inside the request detail panel) to see a breakdown:
- Waiting (TTFB) — time until the server started sending a response
- Content Download — time to download the response body
If TTFB is high (hundreds of milliseconds or more), the slowness is in your database query or server logic — not your frontend code.
If Content Download is high, you are fetching too much data — consider using .select() to request only the columns you need.
Preserving the Network Log
By default, the Network tab clears on navigation — just like the Console. If you need to see requests made before a redirect (for example, the login request that happens before you're sent to the dashboard), enable Preserve log.
Look for the "Preserve log" checkbox in the Network tab toolbar. Check it before reproducing your issue.
The Debugging Workflow
When your data isn't loading:
Open DevTools (F12) and click the Network tab
Click Fetch/XHR to filter to only data requests
Refresh the page or perform the action that should trigger the data load
Find the Supabase request for the data you expected (look for your table name in the URL)
Check the Status column first — is it green (200) or red (4xx, 5xx)?
Click the request and go to the Response tab — read what the server actually returned
Based on what you see: adjust your RLS policy (403), fix your auth flow (401), correct your URL (404), or investigate your component rendering (200 with correct data but not showing up)