Decode nested encodings automatically. Detects Base64, URL encoding and hex through multiple layers and shows every decoding step. Free, in-browser.
You have a blob. It came out of a PowerShell command line, a phishing URL, a webshell, a config file, a CTF prompt, or a WAF log, and it is obviously encoded — but decoding it once produces another blob. That is the normal case, not the exception, and doing it by hand means guessing the format, pasting into a decoder, looking at the result, guessing again.
This tool does that loop for you. Paste the blob, press Analyze, and it repeatedly identifies the outermost encoding and strips it, showing every step: which encoding it detected, what went in, what came out, until nothing recognisable is left. The final row is the plaintext. Everything runs in your browser tab — the decoding functions are the browser's own atob, decodeURIComponent and TextDecoder, called from JavaScript in the page. Nothing is sent to a server, which is what makes it safe to paste a real captured payload.
A single layer of Base64 is invisible to a human and completely visible to a scanner. Every layer added past the first is aimed at something specific:
powershell -enc or a known C2 domain matches the plaintext, and it matches the single-Base64 form once someone writes that rule too. Wrapping the Base64 in URL-encoding produces a byte sequence nobody wrote a rule for.%2557 decoding to %57 decoding to W — is the canonical example.None of this is encryption. Encoding is reversible by anyone with the format; it hides meaning from casual inspection and from naive pattern matching, not from analysis.
The tool detects automatically, but knowing the signatures is what lets you tell a correct decode from a plausible-looking wrong one.
| Encoding | Alphabet | Giveaways |
|---|---|---|
| Base64 | A–Z a–z 0–9 + / with = padding | Length is a multiple of 4; mixed case; one or two trailing =; text that looks like words with no spaces. Base64 of ASCII text often starts with recognisable prefixes — aHR0c is almost always http |
| Hexadecimal | 0–9 a–f only | Even length; no letters past f; often space- or colon-separated in packet dumps. ASCII text in hex is full of 6 and 7 leading nibbles |
| URL / percent | % followed by two hex digits | %20 for space, %2F for slash, %3A for colon. A %25 is an encoded percent sign, which is your tell that a second layer of URL-encoding is present |
| ROT13 | Letters only, structure preserved | Word lengths, spaces and punctuation look like English but the letters are wrong; gur is the, naq is and |
On each pass the tool tests the current string in a fixed order — Base64, then hexadecimal, then URL-encoding, then ROT13 — and the first test that passes wins. It decodes, records the step, and starts again on the result. The loop stops when no test passes or when it reaches the maximum depth, which defaults to 10 and can be set anywhere from 1 to 20. Setting a shallow depth is genuinely useful when you want to inspect an intermediate layer rather than run all the way to the bottom.
The tests are conservative on purpose, because a decoder that accepts anything produces mojibake and calls it an answer:
%XX sequence and a decode result that differs from the input.The built-in sample is VTJWamNtVjBJSEJoZVd4dllXUWxNakJrWldOdlpHVmtJUT09. Running it produces three steps:
| Step | Detected | Result |
|---|---|---|
| 1 | Base64 | U2VjcmV0IHBheWxvYWQlMjBkZWNvZGVkIQ== |
| 2 | Base64 | Secret payload%20decoded! |
| 3 | URL encoding | Secret payload decoded! |
Step 2 is the instructive one. The output already looks like English, and a careless analyst stops there — but %20 is a live URL-encoded space, so there is one more layer. The loop keeps going precisely because "looks readable" is not the stopping condition; "no further encoding detected" is.
The double-URL case behaves the same way: paste %2557 and you get two steps, %2557 → %57 → W. If you only decode once you conclude the input was the literal text %57, which is exactly the confusion the technique is built on.
Two of these are common enough that you should recognise them before they mislead you.
Unpadded Base64 is not detected. The length-multiple-of-four rule means SGVsbG8gV29ybGQ — fifteen characters, "Hello World" with the padding stripped — produces no steps at all. Many real-world emitters drop padding, and URL-safe Base64 (which substitutes - and _ for + and /) fails the alphabet test outright. The fix is manual: restore = padding to the next multiple of four, and translate - to + and _ to /, then paste again. Similarly, Base64 broken across lines with embedded whitespace or newlines will not be recognised — join it into one line first.
Some hex is misread as Base64. Hex digits are all inside the Base64 alphabet, so a hex string whose length happens to be a multiple of four passes the Base64 test, and Base64 is tried first. 646f776e6c6f61642e657865 is 24 characters of hex meaning download.exe, but the tool reports it as Base64 and returns high-byte noise. Drop one byte — 646f776e6c6f61642e6578, 22 characters — and the Base64 test fails on length, hex wins, and you get download.ex. Two workarounds: insert spaces between hex bytes if the length is awkward, or read the step label and distrust any Base64 step whose input was pure [0-9a-f] and whose output is unreadable. Where you are unsure what a hex string even is, the cipher identifier is the better first stop.
Other limits are simply scope. The tool handles four encodings and no others. It will not touch:
H4sI Base64 prefix means the layer under it is gzip, and you will need a different toolA), JavaScript unicode escapes (\u0041), or PowerShell UTF-16LE Base64, whose decode looks like text with a null byte between every character[72,101,108,108,111] or chr() concatenationsWhen the chain stops at something that clearly is not plaintext, that residue is the interesting part: it usually means the innermost layer is one of the above. Compressed data, encrypted data and UTF-16 text all look different from each other and from random bytes, and identifying which you are holding is the next step.
PowerShell command lines. The -EncodedCommand parameter takes Base64 of UTF-16LE, so the first decode gives you text with a null byte between every character. This tool will report the Base64 step, and the output will look like spaced-out letters — that is the expected appearance of UTF-16, not a failure. Strip the nulls and the script is readable.
Phishing URLs. Redirect chains commonly carry the real destination as a Base64 parameter, which is itself URL-encoded because it is riding in a query string. Paste the parameter value alone, not the whole URL, or the surrounding path characters will fail the alphabet tests.
Webshells and dropper scripts. Layered base64_decode and urldecode calls wrapped around an eval are the standard shape. Reading the nesting order in the source tells you the decode order to expect, and the step list here should match it in reverse.
Log analysis and WAF tuning. When a request was blocked and you need to know what it actually asked for, the request line is usually percent-encoded at least once. Double-encoding in a blocked request is itself a finding — legitimate clients rarely encode twice.
CTF challenges. Deliberately deep chains are a genre. Raising the depth limit to 20 and reading the step list is faster than manual iteration, and where the chain stops on something the tool does not handle, the label on the last successful step usually names the family you are dealing with.
?text= URL parameter, which pre-fills the input — handy for bookmarking a case or passing one to a colleague. Remember that anything in a URL is visible in browser history and any proxy log, so do not do this with a payload that is itself sensitive.