Browser-Based API Testing

API Testing & Tooling — Browser-Based API Testing
API Testing & Tooling
Chapter 8 · Browser-Based API Testing

🌐 Browser-Based API Testing

Chapter 1 named the browser as the zero-setup option — nothing to open, nothing to install. This chapter covers three escalating levels of browser-only testing: the address bar, HTML forms, and the DevTools Console's fetch() trick — plus a deeper look at the Network tab first introduced in wdt_lesson_04.

URL Query Parameters

Pasting a GET URL — query string and all — directly into the address bar sends exactly that request, and most modern browsers pretty-print a JSON response automatically in a built-in, collapsible JSON viewer.

https://api.example.com/products?category=electronics&limit=10

This is the simplest possible check for any read-only endpoint — no tool, no headers, no body, just the URL.

HTML Forms: GET and POST

A plain HTML <form> can send a real request without any JavaScript at all. method="GET" builds a query string automatically from the form's named inputs; method="POST" sends them as a form-urlencoded body.

<form action="https://api.example.com/search" method="GET"> <input name="category" value="electronics"> <button type="submit">Search</button> </form>

This is genuinely limited, though: a plain HTML form can't send a JSON body, can't set custom headers like Authorization, and is restricted to GET/POST — no PUT/PATCH/DELETE. It's useful for the simplest cases, and a natural stepping stone to the next section when those limits are hit.

The DevTools Network Tab, Revisited

wdt_lesson_04 introduced the Network tab's basics. For API testing specifically, three things matter most: filtering to Fetch/XHR requests (hiding images/stylesheets/fonts so only actual API calls remain visible), clicking a request to see its Headers/Payload/Response/Timing sub-tabs, and right-clicking a request for Copy → Copy as cURL — which turns any request the page already made into a ready-to-run cURL command, using exactly Chapter 6/7's syntax.

Full Circle: Network Tab → cURL

Right-clicking a login request the page already made and choosing "Copy as cURL" produces something like:

curl 'https://api.example.com/login' \ -H 'Content-Type: application/json' \ --data-raw '{"email":"dana@example.com","password":"..."}'

That's a real, runnable command using Chapter 6's exact flags — captured directly from the browser with no manual reconstruction, useful for reproducing a bug exactly as the page actually sent it.

The fetch() Console Trick

Pasting a fetch() call directly into the DevTools Console gives full control — any method, any header, a JSON body — without leaving the browser or opening any other tool at all.

fetch("https://api.example.com/products", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer eyJhbGci..." }, body: JSON.stringify({ name: "Wireless Mouse", price: 24.99 }) }) .then(r => r.json()) .then(console.log);

URL Bar / Forms vs. the fetch() Console Trick

URL Bar / HTML Forms

Zero setup, but limited to GET/POST, no custom headers, no JSON body — fine for the simplest read-only checks only.

fetch() in the Console

Any method, any header, a real JSON body — the browser's own equivalent of a Postman request, still without installing anything.

TechniqueCan DoLimitation
URL address barSimple GET requestsNo headers, no body, GET only
HTML formGET or POST with named fieldsNo custom headers, no JSON body, GET/POST only
DevTools Network tabInspect any request the page already made; export as cURLObserves existing requests — doesn't build new ones from scratch
fetch() in ConsoleAny method, headers, and JSON bodySubject to the current page's CORS restrictions (see this chapter's gotcha)

💻 Coding Challenges

Challenge 1: Pick the Browser Technique

For each, name the simplest browser-only technique from this chapter that would work: (a) checking a public GET endpoint returns data, (b) sending a POST with a JSON body and a bearer token, (c) reproducing the exact request a page just made as a cURL command.

Goal: Practice matching a testing need to the least-complex browser technique that actually satisfies it.

→ Solution

Challenge 2: Write a fetch() Call

Write the fetch() console snippet to send a DELETE request to https://api.example.com/orders/55 with an Authorization: Bearer abc123 header, logging the parsed JSON response.

Goal: Practice the full fetch() options object — method, headers, and the promise chain.

→ Solution

Challenge 3: Explain the HTML Form Limitation

A developer tries to build an HTML form that sends a JSON body with a custom X-API-Key header. Explain why a plain <form> can't do this, and what technique from this chapter can.

Goal: Practice articulating specifically what HTML forms cannot do, not just that "forms are limited."

→ Solution

⚠️ Gotcha: fetch() in the Console Is Still Subject to CORS

cURL and Postman aren't browsers, so neither one enforces CORS at all — a cross-origin request that works perfectly in cURL can fail with a CORS error when the exact same fetch() call runs from a page's own DevTools Console, because CORS (covered in browser_lesson_05) is a browser-enforced security mechanism tied to whatever page is currently open, not a property of the request itself. A fetch() call to an API that doesn't send the right Access-Control-Allow-Origin header will be blocked in the console even though the identical request succeeds from a terminal — this is one of the most common sources of "it works in Postman/curl but not in the browser" confusion, and it's a browser restriction working as designed, not a bug in the API or in fetch().

🎯 What's Next

The final chapter is the Capstone: Testing a Real API Across All Four Tools — a Postman collection, a VS Code .http file, cURL scripts, and browser testing, all against one real API, plus automating a subset of it in CI.