Sooner or later every developer and scraper needs to do the same thing: grab a request the page just made, change one value in it, and fire it again — without touching the site's UI. Maybe you're testing what happens when a form field is different, probing an API's parameters, or working out exactly which headers and body a request needs before you reproduce it in code. The good news is you don't need special software for the common case. Your browser's DevTools can edit and resend an HTTP POST request directly. This guide shows how, across browsers, plus the dedicated tools for when you outgrow DevTools — and the one thing (CSRF tokens) that trips everyone up.
Why this is a core skill
Every meaningful action on a modern site — searching, filtering, logging in, paginating, "load more" — is an HTTP request, usually a POST or fetch carrying JSON or form data, hitting an API behind the scenes. Being able to capture one, tweak a parameter, and replay it lets you:
- Debug a form or endpoint without clicking through the UI each time.
- Reverse-engineer how a site's hidden API works — which parameters matter, what changes the response.
- Prototype a scraper by confirming a request works by hand before you translate it into Python or another language.
It's the fastest bridge between "I can see the data in the browser" and "I can pull the data in code."
Method 1: Firefox — built-in Edit and Resend
Firefox has the most complete built-in support, and it's the tool the original version of this article recommended — still the right call today.
- Open DevTools with Ctrl+Shift+I (Cmd+Opt+I on macOS) and switch to the Network panel.
- Reproduce the action so the request appears in the list (filter by XHR/Fetch to cut the noise).
- Right-click the request → Edit and Resend.
Modern Firefox opens a proper editor pane where every part of the request is editable:
- Method (change
GETtoPOSTor vice versa) - URL (including query string)
- Request headers (add, remove, or change any header)
- Request body (the POST payload — form fields or JSON)
Adjust what you want and click Send. The new request runs from the browser, with your real cookies and session attached, and the response shows up in the panel. That "same session" part is what makes it powerful: you're testing as the logged-in user, not a blank client.
Method 2: Chrome and Edge — Replay and Copy-as
Chromium browsers (Chrome, Edge) don't offer an inline "edit the fields and send" editor, but they get you there two ways:
- Replay XHR — right-click an XHR/fetch request in the Network panel and choose Replay XHR to resend it exactly as-is. Great for re-firing a request, but no editing.
- Copy as fetch / Copy as cURL — right-click → Copy → Copy as fetch (or Copy as cURL). This is the real workhorse. You get the entire request as runnable code that you then edit freely:
Paste Copy as fetch straight into the DevTools Console, change any value, and press Enter to send it in-page with your session:
fetch("https://example.com/api/search", {
method: "POST",
headers: {
"content-type": "application/json",
"x-requested-with": "XMLHttpRequest",
},
body: JSON.stringify({ query: "laptops", page: 2 }), // <- edit these
credentials: "include",
}).then(r => r.json()).then(console.log);
Or take Copy as cURL to a terminal, tweak the flags/body, and replay it outside the browser entirely. Because cURL and fetch are portable, this method doubles as your first step toward a script.
Safari's Web Inspector is more limited — its cleanest path is likewise "Copy as cURL" and edit in a terminal.
Method 3: Dedicated tools — Postman, proxies, and friends
When the request gets complicated, or you want to iterate on many variants, graduate to purpose-built tooling:
- Postman / Insomnia / Hoppscotch — paste an imported cURL and you get a full request editor with history, environments, and variables. Ideal for methodically sweeping parameter values.
- Interception proxies — Fiddler, Charles, or
mitmproxy. These sit between the browser (or a phone) and the server, capturing every request — including ones DevTools makes awkward — and letting you breakpoint, edit, and replay them. They're also how you inspect HTTPS traffic (after installing the proxy's certificate) and capture from mobile apps. See the broader web sniffers overview for how these fit together.
For a quick one-off, DevTools wins on speed. For serious API reverse-engineering, a proxy plus Postman is the stronger setup.
The gotcha: CSRF tokens and other dynamic values
Here's what stops a replayed request cold, and it's the single most common surprise. Many sites — especially anything transactional or e-commerce — protect state-changing POSTs with a CSRF token (also called an anti-forgery token). It's a one-time, session-bound value the server issues and expects back. Replay a captured request with an old token and the server rejects it: 403 Forbidden or an "invalid token" error.
CSRF tokens aren't the only such value. Watch for:
- Session cookies that expire or rotate.
- Nonces / request signatures computed from the payload.
- Timestamps that must be recent.
- View-state or hidden form fields regenerated per page load.
To replay successfully you have to supply a fresh, valid version of each. In practice that means:
- Load the page (or its precursor request) first to receive a current token, then read it from the response HTML/JSON or a
Set-Cookieheader. - Reuse the same session — keep the cookie jar from step 1 so the token and session line up. (Firefox's Edit-and-Resend and the DevTools Console already run in your live session, which is exactly why they usually "just work.")
- Send the token where the site expects it — a hidden field, a JSON property, or a header like
X-CSRF-Token.
When you move from hand-editing to a scraper, this becomes a two-step fetch: request the page, extract the token, then submit the real request with it attached. Getting that flow right is most of what scraping login-protected sites comes down to.
From replay to scraper
Once an edited request returns what you want, translating it to code is mechanical. Take the Chrome Copy as cURL output and either convert it (Postman and many online tools export cURL → Python requests) or write it by hand:
import requests
session = requests.Session()
# 1) load a page first if you need a fresh token/cookies
session.get("https://example.com/search")
# 2) replay the (edited) POST within the same session
resp = session.post(
"https://example.com/api/search",
json={"query": "laptops", "page": 2},
headers={"X-Requested-With": "XMLHttpRequest"},
)
print(resp.status_code)
print(resp.json())
At scale you'd add rotating proxies, realistic headers, and retry logic — but the core request is the one you just verified in the browser. That's the whole point of learning to edit and resend: it de-risks the scraper before you write a line of it.
Summary
Editing and resending an HTTP POST request is a five-minute skill with outsized payoff. In Firefox, right-click a Network request and choose Edit and Resend for a full inline editor. In Chrome/Edge, use Replay XHR to resend as-is or Copy as fetch / cURL to edit and replay. Step up to Postman or an interception proxy when you need HTTPS capture, mobile traffic, or systematic parameter testing. The one reliable blocker is dynamic anti-forgery values — CSRF tokens, nonces, timestamps — which you defeat by fetching a fresh token in the same session before replaying. Master this and you've got the foundation for reverse-engineering almost any site's API. If you'd rather skip the reverse-engineering and just get the data, scraping.pro can build and run the extraction for you.