Copy as cURL in Chrome DevTools: Every Option Tested

Copy as cURL turns a request from the Chrome DevTools Network panel into a terminal command you can run again outside the browser. Right-click any request in the Network panel, open Copy, and pick Copy as cURL. You get the URL, the method, every request header, your cookies and the body as one command that you can paste into a terminal.

It is one of the most useful buttons in DevTools and one of the easiest to misuse, because that command carries your login. I tested every Copy variant in Chrome 156.0.8078.49 (October 2026) against a small local API. I replayed each copied command and logged exactly what reached the server, so the claims below are measured, not taken from older guides.

Where Copy as cURL Lives in Chrome DevTools

The steps are the same on every desktop OS:

  1. Open DevTools (F12, or Cmd+Option+I on Mac) and switch to the Network panel.
  2. Reload the page or trigger the action, so the request shows up in the list. DevTools only records while it is open.
  3. Right-click the request, hover Copy, and choose a variant.
Copy as cURL in Chrome DevTools: the Network panel right-click Copy submenu in Chrome 156 on macOS, listing Copy URL, Copy as cURL, PowerShell, fetch, fetch (Node.js), HAR and more

The submenu has three groups. The top group copies this request as code. The middle group copies parts of it: request headers, response headers, the response body and the initiator's stack trace. The bottom group copies every request in the list: all URLs, all as cURL, PowerShell or fetch, and a HAR file. If a filter is active, the bottom group switches to "Copy all listed as…" and only includes the requests that pass the filter. That is how you export just the API calls without fonts and images.

On Windows the menu is longer, because cURL comes in two flavors:

The Windows version of the DevTools Copy menu showing Copy as cURL (cmd) and Copy as cURL (bash), plus Copy all as cURL (cmd) and (bash)

I made that screenshot on a Mac by giving the DevTools frontend a Windows user agent. The DevTools source picks the menu items from the platform, and the Mac and Linux menus show a single Copy as cURL, which is the bash version.

Every Copy Variant Compared

Here is everything in the submenu, what it produced in my test and when it is the right tool:

Copy optionWhat you getCarries cookies?Use it for
Copy URLThe request URL onlyNoLinking to an endpoint or a file
Copy as cURLcurl command in bash quotingYes, as -bReplaying in macOS/Linux/WSL/Git Bash, bug tickets for backend devs
Copy as cURL (cmd) (Windows)curl with ^ escaping for cmd.exeYes, as -bReplaying in Windows Command Prompt
Copy as cURL (bash) (Windows)Same output as the Mac/Linux optionYes, as -bWSL or Git Bash on Windows
Copy as PowerShellInvoke-WebRequest with a WebRequestSessionYes, as $session.Cookies.AddReplaying in PowerShell
Copy as fetchfetch() call for a browser consoleNo header; credentials: "include"Re-running a request in the console of the same site
Copy as fetch (Node.js)fetch() call for NodeYes, as a cookie headerScripts, tests, reproducing in Node 18+
Copy as preload element<link rel="preload"> tag—Preloading a font, script or image (greyed out for API calls)
Copy request / response headersHeader block as textRequest: yesComparing two requests side by side
Copy responseThe response body—Saving a JSON payload as a fixture
Copy stack traceInitiator call stack—Finding which code fired the request
Copy all as HAR (sanitized)HAR JSON for every requestStrippedSharing a whole session with a vendor or teammate

"Copy as preload element" was greyed out for every fetch request in my test. It only turns on for GET subresources that can be preloaded, never for the main document or for API calls.

What Copy as cURL Actually Copies

This is the command DevTools produced for a JSON POST from my test page (trimmed of the sec-ch-ua client-hint lines):

curl --url 'http://127.0.0.1:8943/api/orders' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \
  -H 'Authorization: Bearer tok_live_8f2c91' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'session=sess_9a8b7c6d; theme=dark' \
  -H 'Origin: http://127.0.0.1:8943' \
  -H 'Referer: http://127.0.0.1:8943/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; ...) HeadlessChrome/156.0.0.0 Safari/537.36' \
  --data-raw $'{"sku":"KB-87","qty":2,"note":"it\'s \\"urgent\\" & 100% real"}'

A few details matter:

  • The method is implied. There is no -X POST, because --data-raw already makes curl send a POST. DevTools only adds -X when the method is not what the body implies (a PUT or PATCH with a body, for example).
  • Cookies become -b. The Cookie header is turned into a -b argument. That includes session, which my server set as HttpOnly. Page JavaScript cannot read that cookie, but Copy as cURL hands it to you in plain text.
  • Awkward bodies are handled. The body contains a single quote, double quotes, & and %. DevTools switched to bash's $'...' quoting to escape them, and the replayed body was byte-identical.
  • Some headers are dropped. Host, HTTP/2 pseudo-headers and Accept-Encoding are left out. Without Accept-Encoding, the server I tested sent the replay uncompressed, although the browser had received gzip.
Chrome DevTools Headers tab for the POST request, showing the Authorization bearer token and the Cookie header that Copy as cURL includes

Everything you see under Request headers in that screenshot, except Accept-Encoding, Host and Content-Length, ends up in the copied command.

Replay results

I replayed four requests from the copied commands and compared what my server logged against what it had logged for the original browser requests:

RequestBody (browser → replay)Cookie + auth on replayHeader differences
GET with Authorization + X-API-Key0 → 0 bytesBoth presentOnly Accept-Encoding missing
POST JSON60 → 60 bytes, identicalBoth presentOnly Accept-Encoding missing
POST urlencoded form24 → 24 bytes, identicalCookie presentOnly Accept-Encoding missing
POST multipart (text file)304 → 304 bytes, identicalCookie presentOnly Accept-Encoding missing
POST multipart (binary file)453 → 869 bytes, corruptedCookie presentOnly Accept-Encoding missing

For text payloads Copy as cURL is a faithful replay. The binary case is the exception. I uploaded a file containing all 256 byte values, and every byte above 0x7F arrived as the Unicode replacement character, which nearly doubled the body. If the request uploads an image, a PDF or anything else binary, keep the headers from the copied command and replace the --data-raw part with -F 'file=@/path/to/file'.

cURL (cmd) vs cURL (bash) on Windows

The two Windows options produce the same arguments with completely different quoting. Here is the --url line and the body from the same request, as Copy as cURL (cmd) generated them:

curl --url ^"http://127.0.0.1:8943/api/orders^" ^
  -b ^"session=sess_9a8b7c6d; theme=dark^" ^
  --data-raw ^"^{^\^"sku^\^":^\^"KB-87^\^",^\^"qty^\^":2,^\^"note^\^":^\^"it's ^\^\^\^"urgent^\^\^\^" ^& 100^% real^\^"^}^"

cmd.exe has no single-quote strings, so every special character gets a ^ escape, % becomes ^% so it is not treated as a variable, and lines continue with ^ instead of \. The (bash) option on Windows produced output identical to the Mac version, character for character.

The rule is simple: use the variant that matches the shell you will paste into. Command Prompt gets (cmd). Git Bash, WSL, macOS, Linux, CI runners and almost every bug tracker reader get (bash). If you are writing a ticket and don't know where it will be run, use bash: it is the version most people can read and run. I could not run the cmd variant myself, since I tested on a Mac.

PowerShell users should skip both and use Copy as PowerShell. It builds an Invoke-WebRequest call. The user agent and each cookie go into a WebRequestSession ($session.Cookies.Add(...)), and the remaining headers go in a hashtable. It also escapes quotes with backticks, which neither cURL flavor does correctly for PowerShell.

Copy as fetch vs Copy as fetch (Node.js)

The two fetch variants look almost the same but are built for different places.

Copy as fetch is for the browser console. It removes the Cookie header and the user agent, because browsers forbid scripts from setting them. Instead it sets "credentials": "include" whenever the original request carried cookies or an Authorization header, so the browser attaches cookies from its own jar. It also sets "mode": "cors" and fills "referrer". I pasted it into the console of the same page and the server received the session cookie and the bearer token. I then ran the same code in Node 22 and the server got the token but no cookie, which is expected: Node has no cookie jar to include.

Copy as fetch (Node.js) fixes that. It removes credentials, mode and referrer and writes the cookies and Referer straight into headers:

fetch("http://127.0.0.1:8943/api/orders", {
  "headers": {
    "accept": "*/*",
    "authorization": "Bearer tok_live_8f2c91",
    "content-type": "application/json",
    "cookie": "session=sess_9a8b7c6d; theme=dark",
    "Referer": "http://127.0.0.1:8943/"
  },
  "body": "{\"sku\":\"KB-87\",\"qty\":2,\"note\":\"it's \\\"urgent\\\" & 100% real\"}",
  "method": "POST"
});

In Node 22 that replay arrived with the cookie, the token and the identical 60-byte body. Use it to turn one request into a test or a script. The closely related context-menu item Edit and resend as fetch puts the browser-style fetch call into the Console prompt as await fetch(...), with headers that a page script cannot set commented out, ready to edit and run. That is usually faster than copying it when you only want to change one field and resend. If you need to watch the request under bad network conditions while you do that, the network throttling guide covers the presets.

Copy All as cURL, fetch and HAR

The bottom group of the menu copies the whole request list at once. "Copy all as cURL" joins one command per request with ; between them, so the result runs top to bottom as a script. "Copy all as fetch" does the same with fetch() calls. Requests to blob: URLs are skipped, and the single-request items are disabled on them, because a blob only exists inside that tab.

The most useful bulk option for collaboration is Copy all as HAR (sanitized). HAR is the JSON format that browsers, proxies and many vendor support teams read. I checked what "sanitized" removes in my copy:

ItemIn the sanitized HAR?
Authorization request headerRemoved
Cookie request header and the parsed cookie listRemoved
Set-Cookie response headerRemoved
Custom X-API-Key request headerKept
POST bodies (JSON, form, multipart)Kept, in full
Tokens in the URL query stringKept
Response bodiesNot included in my copy (size and type only)
DevTools Settings, Preferences, Network section with the Allow to generate HAR with sensitive data checkbox turned off by default

The unsanitized version is hidden on purpose. It only appears as "Copy all as HAR (with sensitive data)" after you tick Allow to generate HAR with sensitive data under DevTools Settings → Preferences → Network. When I ticked it, the new item showed up at the bottom of the Copy submenu. Leave it off unless you are debugging an auth problem yourself.

Redact Secrets Before You Paste

A copied cURL command is a working login. Anyone who runs the one above becomes me until the session expires. Bug trackers, Slack channels and AI chat windows are all more widely read than the app you are debugging, so redact before you paste:

  1. Cookies (-b '...'). Delete the whole -b argument unless the bug is about cookies. Session cookies are the most valuable thing in the command, and HttpOnly gives no protection here.
  2. Authorization headers. Replace the token with Bearer <redacted>. Do the same for the cookie header in Node.js fetch output and for $session.Cookies.Add lines in PowerShell output.
  3. Custom auth headers. Look for X-API-Key, X-Auth-Token, X-CSRF-Token and anything vendor-specific. DevTools has no way to know these are secrets, and even the sanitized HAR keeps them.
  4. The URL and the body. Signed URLs, ?token= parameters, passwords in login bodies and personal data in JSON payloads all survive every Copy option, sanitized HAR included.
  5. Noise. The sec-ch-ua* and Sec-Fetch-* lines are almost never relevant and make tickets hard to read. Cutting them makes the secrets easier to spot.

A good habit is to replay the redacted command once yourself. If it still reproduces the bug with a placeholder token (for example, a 401 that should have been a 403), the ticket is self-contained. If it needs the real token, write "requires a valid session" in the ticket instead of pasting one. Copying the page URL into bug reports covers the other half of a good ticket.

Faster Ways to Reach the Copy Menu

Right-clicking is the only way to reach the Copy submenu, but the steps before it can be faster:

  • Type in the Network panel's Filter box (for example api/ or method:POST) so the request you need is near the top. The "Copy all listed" items then only export what is visible.
  • Tick Keep log (formerly "Preserve log") when the request happens just before a redirect, or the row disappears before you can right-click it.
  • Use the DevTools command menu (Ctrl+Shift+P / Cmd+Shift+P) to jump to the Network panel or toggle panel settings without hunting through tabs.

For more DevTools habits that save minutes every day, see the Chrome DevTools tips and tricks hub.

Frequently Asked Questions

How do I copy a request as cURL in Chrome? Open DevTools, go to the Network panel, trigger the request, right-click it in the request list and choose Copy, then Copy as cURL. On Windows the menu offers two versions: Copy as cURL (cmd) and Copy as cURL (bash).

Does Copy as cURL include cookies and the Authorization header? Yes. In my Chrome 156 test the copied command carried the Authorization bearer token, a custom X-API-Key header and every cookie, including an HttpOnly session cookie, as a -b argument. Treat the copied command as a password.

What is the difference between Copy as fetch and Copy as fetch (Node.js)? Copy as fetch is meant for a browser console: it drops the Cookie header and sets credentials: "include", so the browser attaches its own cookies. The Node.js version has no credentials option and writes the Cookie and Referer headers into the code, because Node has no cookie jar.

Why does my copied cURL command return different data than the browser? Usually because the session in the command expired, or because the request depends on state the command cannot carry. Chrome also drops the Accept-Encoding header, so the server answers uncompressed, which matters only if the bug is about compression.

Is Copy all as HAR (sanitized) safe to share? Safer, not safe. It removes Cookie, Set-Cookie and Authorization headers, but in my test it kept a custom X-API-Key header and every POST body. Check the file for custom tokens before sharing it.

Can Copy as cURL replay file uploads? Text multipart uploads replayed byte for byte in my test. Binary uploads did not: a 453-byte upload came back as 869 bytes because non-text bytes were replaced. For binary files, rewrite the command with curl -F and the real file path.

Copy as cURL captures the request. The ticket usually also needs the page it came from. Ctrl+Shift+C copies the current tab's URL with one shortcut, with no address bar trip and no data collected. It is the fastest way to put the page next to the command.

Try Ctrl+Shift+C

Copy any URL with one keyboard shortcut. Free forever, no data collected.