Sanitize a curl command before you share it
Runs locally in your browser. Your file never leaves your device.
By processing a file or pasted text here, you agree to the Terms.
…or sanitize a file instead
Pick a plain-text file (or drop one onto the box above). For whole terminal logs, the log file redactor handles up to 20 MB.
“Passwords & secrets in key=value” also governs the name-based masks
this page adds on top: sensitive header names
(authorization, x-api-key, …), credential-named
query and form parameters, and JSON body keys. Cookie values,
-u passwords, URL userinfo passwords, and
--oauth2-bearer are masked by grammar position and stay on
regardless of toggles.
Review these — possibly internal hosts
Hosts that look like private infrastructure (single-label machine
names, intranet suffixes like .corp or
.internal). They were not changed —
the endpoint is usually the point of sharing a repro, and only you
can tell whose name is sensitive. Their lines are marked in the
sanitized pane below.
Review these — possibly secret
Random-looking strings that match no known secret format. They were not masked, because a high-entropy string can be a session token or just a checksum — only you can tell. Their lines are marked in the sanitized pane below.
Original
Sanitized
A copied curl command is your logged-in session, serialized
“Copy as cURL” exists to make requests reproducible, and it is very good
at that — too good to paste anywhere public. The command DevTools puts
on your clipboard carries every cookie your browser held for that site
(the session cookie that is your login, the CSRF token, the
analytics IDs), the Authorization header if the app sends
one, any API keys riding in custom headers, and the entire request body
with whatever the form or API call contained. Anyone who runs it is you,
until the tokens expire or get revoked. Pasting one into a GitHub issue,
a support ticket, a team chat, or an AI assistant hands your ambient
identity to everyone who can read it — and manual redaction reliably
misses the third cookie in a fat cookie: header.
What gets masked — and what the output looks like
Headers with credential-shaped names (authorization,
proxy-authorization, x-api-key,
x-auth-token and relatives) keep the name and the scheme
word but lose the credential:
authorization: Bearer [SECRET-1] still tells the reader
what kind of auth the request used. Cookie headers and
-b strings are masked per cookie, by position — every
value, names kept — because the format itself says what they are.
-u user:password keeps the username and masks only the
password (same rule as URL user:pass@host userinfo): the
username is often the reviewable, repro-relevant half, and an
email-shaped one is still caught by the email pattern.
Credential-named query parameters (token=,
api_key=, sig= …) are masked in URLs and
--referer values. Form bodies get the same key=value
credential detection as every tool on this site; strict-JSON bodies are
walked key-by-key, so "access_token" three levels deep is
masked and re-serialized minified. And one value seen in several places
— header, cookie, body — becomes the same placeholder, so the
sanitized command still shows one credential doing all three jobs.
Everything is spliced into your original text: quoting style, argument
order, backslash or caret line continuations, even the
$ prompt in pasted scrollback stay byte-for-byte intact
outside the masked spans. Both flavors DevTools emits are understood —
bash/POSIX (single quotes, $'…', backslash continuations)
and Windows cmd ("" escapes, caret continuations) — and
prose around the commands is scanned with the ordinary pattern engine,
because real pastes are terminal scrollback, not clean one-liners.
The URL host stays readable — on purpose
Masking api.example.com would gut the repro; the endpoint
is usually why the command is being shared at all. So public-looking
hosts stay. The flip side: hosts that look like private infrastructure
— single-label machine names like buildcache:9945,
intranet suffixes like registry.corp — are flagged in the
review panel, unchanged, for your call; and host:port shapes with
strong enough evidence are masked by the shared detection engine, the
same conservative hostname handling as the
stack trace cleaner. A private
host with a public-looking name will sail through — read the preview.
What it can miss — read this before you share
Detection is pattern-based and best-effort — expand for what can slip through.
Detection is pattern-based and incomplete by construction, and this
page is deliberately not a shell parser — it does quote-aware
tokenization, nothing more. Command substitutions
($(…), backticks) and variable references stay literal
text; a command with an unterminated quote falls back to plain pattern
scanning and says so; PowerShell quoting is not understood at all
(DevTools’ “Copy as PowerShell” emits a different command entirely). A
secret in a custom header with a bland name is only caught if its value
matches a known pattern or is long and random enough for the
suspicious-string flagger — random tokens under about 20 characters
stay below its statistical floor, and prose-shaped secrets are
invisible to it. Inline bodies that are not text are left byte-identical
and flagged, and @file bodies reference contents this page
never sees. The side-by-side preview exists so the final human pass
takes seconds — do it.
Sharing a whole capture instead of one request? A HAR file is the many-request version of this problem — the HAR file sanitizer applies the same header, cookie, and body treatment across every entry.
Frequently asked questions
Does this page send my curl command anywhere?
No. This is a static page with no server behind it, and its Content-Security-Policy is set to connect-src ‘none’ — the browser itself refuses to let this page make any network request, to us or to anyone. You can verify that: open DevTools, watch the Network tab, and paste a command — no request carries your text. Sanitizing runs in this tab’s memory and nothing persists after you close it.
What does “Copy as cURL” actually capture?
The whole ambient identity of your browser session at that moment: every cookie your browser had for that site (session, CSRF, analytics, all of them), the Authorization header if the app uses one, API keys in custom headers, and the full request body. Pasting one into a ticket, a chat, or an AI assistant is functionally the same as handing over your logged-in session — anyone who replays it is you until the tokens expire.
Will the sanitized command still run?
It still parses and executes — quoting style, argument order, and line continuations are preserved byte-for-byte outside the masked spans, and the replacement placeholders are plain bracketed tokens that are safe in every quoting context this page handles. Our test suite re-parses every sanitized command and additionally checks bash syntax on real output. The server will of course reject the placeholder credentials — that is the point; whoever needs a working repro substitutes their own.
Why is the URL host still visible?
Because the endpoint is usually the reason you are sharing the command at all — masking api.example.com would gut the repro. The trade-off is deliberate and it cuts the other way for private infrastructure: hosts that look internal (single-label machine names, or suffixes like .corp and .internal) are flagged in the review panel for your call, and host:port shapes with strong enough evidence are masked by the shared detection engine. A public-looking hostname that is actually private will stay visible — check the review panel and the preview.
What about PowerShell?
DevTools’ “Copy as PowerShell” does not emit curl at all — it emits Invoke-WebRequest, which is a different command this page does not parse. And a curl command written with PowerShell’s own quoting (backtick escapes and continuations) is not understood either. Paste the bash flavor (Linux, macOS, WSL) or the Windows cmd flavor — the two things DevTools actually produces under “Copy as cURL”.
Why do repeated values get the same placeholder?
Each distinct value maps to a stable token like [SECRET-1], assigned in first-seen order — including across positions, so a session token that appears in the Authorization header, again in a cookie, and again in the JSON body becomes the same [SECRET-1] in all three places. Whoever reads the sanitized command can still see it is one credential doing all three jobs; the value itself is gone.