Free · No Signup

Redacting a Screenshot of Code, a Terminal, or a Log

A capture of source code, a shell session or a log is self-describing and repetitive — the value you boxed is usually somewhere else in the same frame, and the label beside the box announces what the box is hiding.

🔒 No upload · Runs in your browser · Instant download

Most of the text-in-an-image problems described on this site have the same shape. A value sits in a field, you cover the field, the value is gone. A bank statement behaves like that. A driving licence behaves like that. A chat thread mostly behaves like that, and the hard part is noticing every field rather than covering it.

A screenshot of source code, a terminal session or a log file does not behave like that at all, and it fails in three ways that have nothing to do with how carefully you aim. It repeats itself: the hostname you covered in the command is still in the prompt, in the output, in the certificate error and in the window title. It labels its own secrets: a line reading AWS_SECRET_ACCESS_KEY= followed by a black rectangle has told the reader the type and the format of what is behind the rectangle. And it is set in a monospaced font, where every glyph occupies the same horizontal advance, so the width of your box is also a count of the characters underneath it.

There is a fourth difference that pushes in the opposite direction. On a bank statement the recipient needs one figure and you can bury everything else. On a stack trace the recipient has to read nearly the whole frame to be any use to you, so the usual safe default — cover generously, apologise later — destroys the reason you sent the capture. That tension is what this page is about: a redaction procedure organised by value rather than by region, the sweep list for the parts of a developer capture people reliably forget, the reason the better answer is usually to send text instead of a picture, and exactly what this editor can and cannot do when an image really is the right artefact.

Mode
Shape

Drop your image here

Or click to browse · Paste with Ctrl+V also works

PNG · JPG · WebP · GIF
How It Works
1

Open

Drop your image in or paste from clipboard.

2

Pick Mode

Black Box, Blur, or Pixelate.

3

Select Areas

Rectangle, oval, or freehand lasso — then hide what you selected.

4

Download

Hit Download PNG. Done.

SquooshNeed to shrink your image after editing? Squoosh is a free browser-based image compressor with no upload required.

Visit Squoosh →
Guide

One sentence carries this page: code, terminal output and logs are self-describing and repetitive, so the leak is rarely the region you covered — the same value is somewhere else in the frame, the label beside your box names what is under it, and in a monospaced font the width of the box counts the characters.

Three properties of the medium that break the one-box-one-secret habit

These are not edge cases. They are how code is written and how shells are designed, and they compound with each other.

It repeats itself on purpose. Good systems echo their context so you can tell where you are. Run one command against one host and that host appears in the shell prompt, in the command you typed, in the first line of output, in the TLS error forty lines down, in the terminal tab title and in the window title. A customer identifier that appears once in a log line appears again in the request id, in the URL of the admin tab you had open behind it, and in the branch name you were working on. Covering the occurrence you were looking at is the normal outcome of region-by-region redaction, and on this kind of capture it is almost never sufficient.

It labels its own secrets. Configuration is written as a name next to a value, which means the name survives the box. DATABASE_URL= followed by a rectangle narrows the hidden string to a scheme, a host, a port and a set of credentials. Credential formats are published deliberately so that scanners can recognise them: GitHub documents a token-type-to-prefix table in which a classic personal access token begins ghp_ and a fine-grained personal access token begins github_pat_. If the prefix is outside your box, you have published the type of the secret and left only the random part covered — which is the right way round, but it means the box has to be judged as a partial redaction rather than a complete one.

It is monospaced. In a fixed-width face every character occupies the same horizontal advance by definition, so a cover that spans a run of text is a measurement of how many characters that run contained. Compare it against any visible line of the same font and the arithmetic is trivial. For a lot of values the length is most of the answer: a card number, a postcode, an order reference, an internal employee id, a four-segment version string. How much of a value you can safely leave visible, and why length is itself a disclosure, is worked through in partial redaction: how much can you leave visible.

Alignment makes this worse rather than better. Columnar log output and aligned assignment blocks mean your box inherits the grid, so a reader can tell which column a covered value sat in and therefore what kind of value it was, without reading a single glyph.

Redact by value, not by region

The fix for repetition is to invert the procedure. Do not sweep the image looking for things to cover; build a list of distinct sensitive values first, then hunt each one across the whole frame.

1. List the values, not the places. Before touching the editor, write down the distinct sensitive strings visible anywhere in the capture: this hostname, this token, this username, this customer email, this bucket name, this path. Four or five entries is typical. Twenty means the capture is too wide and you should narrow it instead.

2. Scan the whole frame once per value. One pass per entry on your list, reading the frame edge to edge rather than centre-out. This is slower and it is the only thing that reliably catches the fifth occurrence. The eye reads the middle of a terminal; the occurrences hide at the top and the bottom.

3. Give each value one treatment. Cover every occurrence of a value the same way, or deliberately leave every occurrence visible. Half-covering a value across a capture is the worst outcome available: the visible instances confirm the hidden ones, and the pattern of covers tells a reader which strings you considered sensitive.

4. Review value by value, not box by box. At the end, go back through your list and ask of each entry whether it still appears anywhere in the exported image. Counting your boxes tells you nothing, because the question was never how many boxes you drew.

The sweep list for a developer capture

Ordered roughly by how often it is forgotten rather than by how serious it is.

The prompt line. Many default prompts carry the account name, the machine name, the full working directory, the git branch, and whatever your shell adds: a virtualenv name, a Kubernetes context, a cloud profile, an exit code. A single prompt line can disclose who you are, which company you work for, which customer cluster you are pointed at and which ticket you are working on.

Absolute paths. /Users/ and /home/ and C:\Users\ are followed by a real name far more often than people expect, and that name then appears in every stack frame, every import error and every build log in the capture. Mounted volume names, network share names and external drive labels belong in the same category.

The repository, the branch and the ticket. A private repository name, an internal codename, a branch like fix/acme-corp-billing-crash, a commit message quoting a customer. These tend to sit in the editor chrome, where nobody looks.

Configuration keys as well as values. The key name is a description of the covered value. If the key name itself is sensitive — a feature flag naming an unannounced product, a vendor you have not disclosed — cover the key too, and accept that the line is now unreadable.

Endpoints, hosts, ports and bucket names. An internal hostname is a piece of your network map whether or not it resolves from outside, and staging environments resolve from outside more often than anyone intends. Database names, queue names and bucket names are in the same family.

Anything inside a command you pasted. A bearer token in a curl line, a password in a connection string, a jump host in an ssh invocation, a signed URL with its signature intact, an API key passed as a query parameter. Shell history hints and autocomplete suggestions render these in grey text you did not type and may not have noticed.

Log lines are personal data. One line containing an email address, an IP address, a user agent and a timestamp describes a person, and a hundred such lines describe a hundred people. Machine-generated output feels impersonal, which is exactly why it gets attached to tickets unedited.

Identifiers that look like plumbing. Request ids, trace ids, session ids, correlation ids. They look meaningless, and they are meaningless to you, but they are searchable in systems other people can reach, and a session identifier is occasionally a live credential.

The scrollback. A maximised terminal can hold a hundred lines, most of which you were not reading when you pressed the shortcut. Earlier commands in that buffer are the single most common source of a leaked value on this kind of capture, because the thing you are now carefully covering was echoed in full six commands ago.

The editor around the code. The file tree, the row of open tabs, the problems pane, the source-control panel, the terminal tab titles, extension notifications, a toast from a messaging app, and inline AI completions sitting in the buffer as ghost text. None of it is the thing you meant to share and all of it is in the frame.

The window title and everything behind it. Titles routinely concatenate the file, the project and the branch. If the capture is a whole screen rather than a window, the taskbar, the clock and the next application along came too.

The move that beats redaction: send text

For most code and terminal content, the right answer is not a better-redacted picture. It is not a picture.

Text can be substituted; an image can only be covered. In a text editor you replace a hostname with EXAMPLE_HOST at every occurrence in one operation, and the result is still something your reader can compile, parse, diff, search and copy. In an image the only operation available is concealment — this editor contains no text-drawing calls at all, so there is no way to write a placeholder over a covered value — and a covered value is a hole precisely where the reader needed a name.

Consistency becomes visible. Three identical black boxes do not tell anyone whether they hide one value or three. Three instances of EXAMPLE_HOST say plainly that it was the same host each time, which is frequently the fact that solves the problem.

Find-and-replace does not get bored. It catches the occurrence in the scrollback, the one in the comment and the one in the window title you pasted along with everything else. Your eye does not.

And the three mechanisms above simply stop applying. There is no box width to measure, no grid for a cover to inherit, and no label-next-to-a-rectangle, because you can rewrite the label too.

Choose the image only when the rendering is the evidence: a layout or styling bug, a colour, a font, a profiler flame chart, a dashboard, a crash dialog, an installer step, a mobile screen, or output you cannot reproduce on demand. In those cases, invest the effort upstream rather than in the editor. Open a new window instead of using the one you have been working in. Shorten the prompt for the duration. Clear the scrollback. Resize the window small so the capture contains the command and its output and nothing else. Re-run only the step that matters. A capture that needs two boxes is a fundamentally safer artefact than a capture that needs twenty, and the difference in effort is about a minute.

If what you covered was a credential, rotate it first

This is the one category on the whole site where the sensitive thing can be made harmless retroactively. A date of birth is permanent; a street address is durable; a token is a string a system will stop honouring the moment you ask it to. That changes the order of operations.

Rotate the credential, confirm the old value no longer works, and only then redact the capture — at which point the redaction is record-keeping rather than remediation. It also defuses every mechanism described above: if the secret is already dead, the occurrence you missed in the scrollback is an embarrassment rather than an incident. Doing it the other way round means betting that your box-drawing was perfect, on an image that may already have been seen by whoever was watching your screen. The field-by-field detail for credential captures specifically, including network tabs and authorisation headers, is in hide an API key in a screenshot.

The same logic does not extend very far. Session identifiers can usually be invalidated by signing out everywhere. Internal hostnames, repository names, customer records and your own username cannot be rotated at all, which is why they deserve more care than the token, not less.

What this editor can and cannot do on a code capture

Worth knowing before you start, because a dense log is the wrong place to discover a limitation.

Regions only, nothing automatic. There is no text detection and no way to cover every instance of a string at once. Four hundred visible log lines are four hundred lines of manual work, which is the strongest practical argument for a narrower capture or for sending text.

Black Box is the mode for this. It fills your selection with flat #111111, so nothing remains to recover. Blur is a fixed factor-of-ten downsample of the selection scaled back up; Pixelate replaces each block with one sampled pixel, the block size being the shorter side of your selection divided by twelve with a floor of six pixels. Both preserve coarse structure by design, and coarse structure is exactly what a reader needs when the hidden string has a known format. On a code capture every string has a known format, and monospaced text is the worst case of all, because the surviving blocks line up with the character cells.

Rectangle is the shape that fits. A line of code is an axis-aligned run of cells. An oval clips the ascenders and descenders at the ends of the run, and a lasso either leaves a sliver of a glyph or swallows the identifier next door.

Small covers fail silently. A rectangle drag under about four image pixels, or an oval under six, is discarded with no message, and a lasso needs at least three sampled points before it applies. Covering a single short value on a small capture can land inside those thresholds without any indication that nothing happened.

No crop, resize or rotate. The canvas is created at the source image’s exact pixel dimensions and nothing in the code alters them, so the export matches what you captured. Narrow the terminal before the screenshot rather than blacking out the rest of the screen afterwards.

One file at a time, and no memory between files. The file input takes a single file and the drop handler reads only the first file dropped, so dragging in a folder of captures opens exactly one with no error. Loading the next image resizes the canvas and resets the undo history with no prompt, so download each finished PNG before moving on.

Your clipboard still holds the original. Pasting a capture in with Ctrl+V works, but there is no clipboard-write code anywhere in the editor, so a paste still produces the unredacted image. Pressing paste in the ticket after redacting attaches the original. Attach the downloaded PNG.

Nothing leaves the browser. There is no fetch, XMLHttpRequest or WebSocket call in the editor and no browser storage of any kind; the image stays in the tab and the PNG is written from the canvas on your own machine. That property matters more here than almost anywhere else, because a capture containing a live credential is the exact file you do not want to hand to a third party while you are still deciding whether to rotate it.

Common mistakes and misconceptions

“I covered the key, so the key is safe.” You covered one rendering of the key. The variable name beside it, the prefix before your box, the width of the box and the four other places it appears in the frame are all still there.

“It is only my local dev environment, nothing in it is real.” The paths are real, the username is real, the repository name is real, and local databases are seeded from production copies often enough that this is a poor assumption to make quickly.

“I blurred it, so it is unreadable.” Monospaced text with a known format is the most favourable possible case for reconstructing a value from coarse structure. If you would not accept a blur over a card number, do not accept one over a token.

“The width of the box is irrelevant.” In a fixed-width font the width is a character count, and alignment tells a reader which column the value sat in.

“Nobody is going to read my scrollback.” It is the cheapest text in the image to read, it is right there, and it is where the unredacted copy of the value you just covered usually lives.

“Log output is machine data, not personal data.” An email address, an IP address and a user agent on one line is a person, however automatically it was generated.

“A screenshot is easier for whoever is helping me.” It is easier for you. They cannot copy from it, search it, paste it into a terminal or diff it against anything, and they will usually ask you to type out the part they need.

“I will redact the attachment and leave the draft as it is.” The original is still in the ticket draft, the clipboard, the screenshots folder and whatever syncs that folder. Replace the attachment and clear the rest.

“Internal hostnames are not reachable from outside, so they do not matter.” They are a map of the inside regardless, they are a convincing detail in a phishing message, and the staging one is reachable more often than the architecture diagram suggests.

Code and Terminal Captures Leak Differently From Every Other Screenshot

A screenshot of source code, a shell session or a log file breaks the assumption that the rest of this site runs on, which is that a sensitive value sits in one place and covering that place removes it. Three properties of the medium get in the way, and they are not edge cases but the way code and shells are designed. Code and shells repeat their context deliberately, so a hostname you cover in a command is still present in the prompt above it, in the first line of output below it, in a TLS error further down and in the window title. Configuration labels its own secrets, so a variable name left visible beside a black rectangle describes the type and format of whatever is behind the rectangle. And the whole frame is set in a monospaced font, where every glyph occupies the same horizontal advance, which means the width of your cover is also a count of the characters it hides. A fourth difference pulls in the opposite direction: on a bank statement the reader needs one figure and you can bury the rest, while on a stack trace the reader has to see nearly everything to be any use, so covering generously destroys the reason you sent the capture at all.

The procedural fix for repetition is to invert the order of work. Build a list of the distinct sensitive values visible anywhere in the frame before you touch the editor, then scan the entire capture once per value, reading edge to edge instead of centre outwards, because the occurrences that get missed sit at the top and the bottom rather than in the middle where the eye settles. Give each value a single treatment, covered everywhere or visible everywhere, since half-covering a value is the worst available outcome: the visible instances confirm the hidden ones and the pattern of covers reveals which strings you judged sensitive. Then review value by value rather than box by box, because the number of rectangles you drew was never the question. If the list runs past five or six entries, the honest conclusion is usually that the capture is too wide and a narrower one would need a fraction of the work.

The parts people forget are fairly consistent. The shell prompt carries an account name, a machine name, a working directory, a git branch and often a cloud profile or cluster context. Absolute paths embed a real home-directory name that then recurs in every stack frame in the frame. Repository names, branch names and commit messages sit in editor chrome where nobody looks, and branch names quote customers surprisingly often. Configuration keys describe their covered values, endpoints and bucket names map an internal network whether or not they resolve externally, and commands pasted into a shell carry bearer tokens, connection strings and signed URLs, sometimes rendered as autocomplete ghost text you never typed. Log lines combining an email address, an IP address and a user agent describe a person however mechanically they were produced. Identifiers that look like plumbing, such as request, trace and session ids, are searchable by people who can reach the systems that minted them. And the scrollback above the visible command is the most common single source of a leaked value, because the string you are carefully covering now was very likely echoed in full six commands ago.

For most code content the better artefact is not a better-redacted picture but no picture. Text can be substituted rather than merely concealed: one placeholder per distinct value, applied at every occurrence in a single operation, leaving a snippet the reader can still compile, parse, diff, search and copy. Consistency becomes visible, find-and-replace does not get bored, and none of the three leak mechanisms apply because there is no box width to measure and no label left stranded beside a rectangle. Reserve the screenshot for cases where the rendering is the evidence, such as a layout bug, a colour, a profiler chart, a crash dialog or output you cannot reproduce, and then spend the effort upstream: a fresh window, a shortened prompt, a cleared scrollback and a small window produce a capture needing two covers instead of twenty. One last ordering rule that is specific to this category: a credential is the rare sensitive value that can be made harmless after the fact, so rotate it, confirm the old value is dead, and treat the redaction as record-keeping. Internal hostnames, repository names, customer records and your own username cannot be rotated at all, which is why they deserve more care than the token rather than less.

Frequently asked questions

Should I screenshot code at all, or paste the text instead?

Paste the text, unless the rendering itself is the evidence. In text you can substitute: rename a hostname to EXAMPLE_HOST everywhere it appears, replace a token with REDACTED_TOKEN_1 everywhere it appears, and the snippet is still something the reader can compile, parse, diff, search and copy. In an image you cannot substitute at all. The editor on this page contains no text-drawing calls of any kind, so covering is the only operation available to you, and a covered value is a hole exactly where the reader needed a name. Text also removes the three mechanisms that make code captures leak in the first place: there is no monospaced box width for anyone to measure, there is no scrollback you forgot was in the frame, and a find-and-replace catches every occurrence of a value rather than the two or three your eye happened to land on. Screenshot when the picture genuinely is the point: a layout or rendering bug, a colour, a profiler flame chart, a dashboard, a crash dialog, an installer step, or output you cannot reproduce on demand. When that is the case, produce a capture that needs very little covering instead of covering a lot. Open a fresh window, shorten the shell prompt, clear the scrollback, make the window small, and re-run only the command that matters.

I put a black box over the token. Why is that not enough?

Because a terminal or an editor announces what it is hiding, repeats it, and measures it for you. First, the label survives. A line reading AWS_SECRET_ACCESS_KEY followed by a black rectangle tells a reader the type, the owner and the approximate format of what is behind the rectangle. Credential formats are published deliberately so that scanners can spot them: GitHub documents a token-type-to-prefix table in which a classic personal access token begins ghp_ and a fine-grained personal access token begins github_pat_, so the prefix you left visible before the box is part of the answer. Second, the value is usually somewhere else in the same capture. The same token appears in the curl command, in the shell history hint, in the error body below it and in an export line further up the scrollback; the same hostname appears in the prompt, in the command, in the output and in the window title. Third, the width of the box is informative in a way it is not on a proportional font: in a monospaced face every glyph occupies the same horizontal advance, so a cover spanning a run of characters is also a count of them, and for structured values a length plus a format is most of the way to a guess. And none of that is the main point. A credential is revocable, which almost nothing else you redact is. Rotate it, confirm the old value is dead, and then redact the capture as bookkeeping. Once the secret is invalid, missing the fifth occurrence of it stops being an incident.

How do I replace values without breaking the thing my reader needs to read?

Treat it as substitution rather than deletion, and keep it consistent. Work from a list of distinct values rather than a list of places: one placeholder per value, used at every occurrence, so that a reader who sees EXAMPLE_HOST twice knows it was the same host twice. That property is the whole reason text beats a picture here, because three identical black boxes do not tell anyone whether they covered one value or three. Make placeholders obviously fake and never plausible: ACME_INTERNAL_1 is safe, a real-looking hostname or a real-looking account number is not, because somebody will eventually try it or file a ticket against it. Preserve shape only where the shape is part of the bug. If the failure is a length limit, an encoding problem or a character-class validation, say so in words and keep the length or the character class; otherwise a short placeholder is better than a long one, since an exact-length stand-in republishes the length you were trying to hide. Keep everything that is structure rather than content: indentation, line numbers, key names, field order, the shape of the stack, the order of the log lines. Those are what makes the paste diagnosable. Then add one sentence saying what you replaced, so nobody spends twenty minutes debugging your placeholder. And check the replacement did not change the error: substituting a value that the code validates can turn the bug you are reporting into a different one.

What can this editor actually do on a terminal or IDE capture?

It covers rectangular, oval or freehand regions you draw, and nothing in it is automatic: there is no detection of text, no find-all and no way to cover every instance of a string at once, so a dense log is manual work line by line. Use Black Box, which replaces the pixels inside your selection with flat #111111 and leaves nothing to recover. Blur is a fixed factor-of-ten downsample of your selection scaled back up, and Pixelate replaces each block with a single sampled pixel, the block size being the shorter side of the selection divided by twelve with a floor of six pixels. Both keep coarse structure deliberately, and coarse structure is exactly the help a reader needs when the hidden string has a known format, which on a code capture is always. Monospaced text is the worst case for both, because the surviving blocks line up with the character cells. Rectangle is the shape that fits: a line of code is an axis-aligned run of cells, and an oval or a lasso either clips the tops of glyphs or swallows the token next door. Three limits worth knowing before you start. Drags that are too small are discarded with no message, under about four image pixels for a rectangle and six for an oval, and a lasso needs at least three sampled points, which is easy to trip when covering a single short value. The editor cannot crop, resize or rotate, since the canvas is created at the source image pixel dimensions and nothing changes them, so narrow the terminal window before you capture rather than covering the rest of the screen afterwards. And it handles one file at a time, with the next image resetting the undo history without a prompt, so download each finished PNG first. Two privacy notes specific to this job: nothing leaves the browser, as the editor contains no fetch, XMLHttpRequest or WebSocket calls and no browser storage of any kind, which matters when the frame still contains a live credential; and although you can paste a capture in with Ctrl+V, there is no clipboard-write code, so your clipboard still holds the unredacted original. Attach the downloaded PNG instead of pasting into the ticket.