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.