When an API call fails in a web app, it’s easy to thrash: refresh, change code, retry, and hope. This guide gives you a step-by-step workflow you can reuse in Firefox so you can move from “it fails” to “here’s the exact failure mode” quickly.
The goal is not heroics. It’s a reliable sequence you can repeat under pressure.
Step 0: Freeze the problem (what exactly is failing?)
Before opening any tools, write down one sentence: “When I do X, I expected Y, but I got Z.” It keeps you from fixing the wrong thing.
Now decide which bucket you’re in:
- Request never leaves the browser (likely CORS, mixed content, blocked by extension, JS error).
- Request is sent, server rejects it (auth, validation, wrong URL/method, missing header/body).
- Server accepts it, response is wrong (backend logic, wrong environment, caching, stale data).
You’ll confirm the bucket in the next step.
Step 1: Capture the failing request in Firefox DevTools (Network tab)
Open DevTools in Firefox, go to Network, and reproduce the issue once.
- Turn on Persist Logs so navigation doesn’t wipe evidence.
- Use the filter box for a partial endpoint path (for example, /api/ or graphql).
- Click the request that corresponds to the failing action.
From that one request, you can usually answer: did it happen, how long did it take, and what status came back?
Step 2: Read the request like a receipt (URL, method, headers, body)
In the request details, check these in order. This is the “receipt” that tells you what the browser actually sent (not what you think your code sent).
- URL: correct host, path, and query string. Watch for staging vs production, or missing base paths.
- Method: GET vs POST vs PUT/PATCH/DELETE. A wrong method often yields 404/405.
- Request headers: especially Authorization, Content-Type, and Accept.
- Request body: confirm it exists when it should, and matches the server’s expected shape.
If any of these are wrong, you already have a concrete fix to make (and something you can verify after).
Step 3: Interpret the response with a small status-code playbook
Status codes aren’t just numbers; they’re routing signs. Here’s a compact playbook you can reuse.
- 200–299: the server says “ok.” If the UI is still wrong, focus on response data shape, caching, or frontend parsing.
- 301/302/307/308: redirects. Common cause of “works in Postman but not in browser” if auth/cookies differ.
- 400: bad request. Usually wrong JSON shape, missing required field, or invalid query param.
- 401: unauthenticated. Token missing/expired, cookie not sent, wrong audience/issuer, clock skew.
- 403: authenticated but not allowed. Role/permission mismatch, CSRF issues, or origin restrictions.
- 404/405: wrong endpoint or wrong method.
- 409: conflict. Often duplicate/unique constraint or state mismatch.
- 415: unsupported media type. Frequently a missing or wrong Content-Type.
- 422: validation errors with field-level details (check response JSON).
- 429: rate limited.
- 500–599: server-side failure. You still want the request “receipt” to hand to whoever owns the backend.
Read the response body too. Many APIs include a machine-friendly error code that points directly to the problem.
Step 4: Run the “Auth & Session” quick checks (cookies, tokens, CSRF)
Auth problems can look like anything, so it helps to check them systematically.
- Is the Authorization header present? If you expect a Bearer token, confirm it’s there and not “undefined”.
- Are cookies being sent? In request headers, look for Cookie. Missing cookies can be SameSite, domain, or “credentials” settings.
- Is there a CSRF token requirement? Some systems require a header like X-CSRF-Token for state-changing requests.
- Is the request going to the correct environment? Tokens are often environment-bound (staging token won’t work on prod).
If the response is 401/403, this step usually finds the root cause faster than staring at code.
Step 5: Use a CORS decision flow (preflight, headers, and “it never hit the server”)
CORS is the classic case where the browser blocks you before the app can handle anything.
- Do you see the request at all in Network? If not, check the Console for a CORS error and confirm the page is using https when the API requires it.
- Do you see an OPTIONS preflight? If yes, click it and check whether it failed (often 4xx/5xx) or lacks required response headers.
- Look for these response headers on the preflight/response: Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers.
- If you’re sending cookies/credentials: the server must also send Access-Control-Allow-Credentials: true, and the allow-origin can’t be a wildcard.
CORS fixes are server/config fixes, but Firefox is still where you can prove exactly what the browser asked for and what the server replied with.
Step 6: Prove the fix with a clean retest (avoid false “it works now”)
Once you change something, you want a retest that’s hard to argue with.
- Hard reload once (to avoid stale JS), then reproduce exactly the same steps.
- Compare the before/after request: URL, method, headers, body, and status.
- Check caching: if it’s a GET request, verify whether a cached response is being used.
- Save evidence: copy the request/response details or take a note of the request id/time and status.
This is where your workflow pays off: you can show what changed, not just that it “seems better.”
Takeaway: the reusable loop
When an API call fails in the browser, reuse this loop: capture the failing request, read it like a receipt, interpret the status, then run focused checks for auth and CORS. Finish by proving the fix with a clean retest and a clear before/after comparison.
It turns debugging from guesswork into a repeatable habit.