Help
Everything you need to drive Hackvertor: converting data with tags, letting the autodecoder unpick unknown encodings, writing and sharing your own conversion tags, and running payloads in HackPad.
What is Hackvertor?
Hackvertor is a conversion tool for web security research. Instead of picking an encoding from a dropdown, you wrap text in tags — small, nestable markers that transform whatever they contain. Because tags nest, you can build up arbitrarily deep encoding chains and see the result update live.
The site is built around five things:
- The converter — the home page, where you encode and decode text with tags.
- The autodecoder — hands it an unknown blob and it works out the encoding chain for you.
- The tag store — browse, install and publish conversion tags written in JavaScript.
- HackPad — an isolated iframe for running HTML and JavaScript payloads with control over CSP, charset and content type.
- The hacking room — broadcast a payload to everyone in a room and see how each browser renders it.
Every tag runs inside a sandboxed iframe with a restrictive CSP, so tag code never touches the main page.
Getting started
You can use the converter, HackPad, Snippet and browse saved URLs without an account. Logging in (GitHub OAuth, via Login in the nav) additionally lets you:
- install tags from the tag store
- write and publish your own tags
- save public URLs and HackPads
- submit encoding tests, like tags and follow people
The converter
The converter has two editors: Input on the left and Output on the right. You write tags in the input; the output shows the converted result.
Applying tags
Above the editors is the tag menu, grouped by category (Array, Charsets, Compression, Convert, Email, Encrypt, Hash, IP, Math, SQLi, String, Utils, Variables, XML, XSS). Clicking a tag wraps the current selection in the input — or inserts an empty pair of tags if nothing is selected — and leaves the selection inside the tag so you can keep typing.
Tags that can decode as well as encode expand into a submenu with encode, decode and decode → encode. Hovering a tag shows its description and the help text for each of its arguments.
The Search tags… box above the menu is usually faster: type part of a tag name and the categories are replaced by flat lists of matching tags under Encode, Decode and Decode → Encode.
The editors
- Autocomplete. Type
<@in the input to getencode,decode,decodeEncodeandautodecode. Once you've picked one, the completion list becomes every installed tag name, pre-filled with that tag's default arguments and its closing tag. - Tag highlighting and tooltips. Hackvertor tags are highlighted in the input, and hovering one shows what the tag does.
- Unicode highlighting.Any non-ASCII character is highlighted in red in both editors. Invisible characters (zero-width spaces, tag characters, variation selectors, bidi controls) are drawn as a red badge showing their codepoint, so you can see the things you normally can't.
- Character info. Select a single character in either editor and a panel appears in the bottom right with its name, codepoint, decimal value, UTF-8 and UTF-16 bytes, HTML entity, JavaScript escape and percent-encoding.
- Selection matches. Selecting text highlights every other occurrence of it in the same editor.
- Length counters.The yellow number next to “Input:” and “Output:” is the character count. A second red number appears when the UTF-8 byte length differs — a quick signal that the text contains non-ASCII characters.
Buttons and panels
| Control | What it does |
|---|---|
Convert | Runs the conversion manually. |
Clear | Empties both editors. |
Clear tags | Strips every Hackvertor tag from the input, leaving the raw text behind. |
Copy as HTML | Copies the input to the clipboard as text/html rather than plain text. |
← Output | Moves the output back into the input so you can chain another round of conversion. |
Save | Saves the input as a public or private URL — see saving and sharing. |
Below the buttons are four collapsible panels:
- Autodecoder — continuously tries to work out how the input is encoded. See the autodecoder.
- Options — Real-time conversion is on by default and re-converts on every keystroke. Turn it off and use
Convertif you're working with slow tags or very large inputs. - Extras —
Debugreplaces the output with the parsed abstract syntax tree as JSON, which is the fastest way to see why a tag isn't being recognised.Select inputandSelect outputselect all text in an editor.Send to HackPadopens the output in HackPad as either JS or HTML, letting you set the CSP and charset on the way.Send to Snippetopens the input in the Snippet image editor. - History— the last 1000 conversions, stored in your browser's local storage. Click an entry to restore that input and output.
Tag syntax
A Hackvertor tag looks like an HTML tag with an @ after the angle bracket. The name in brackets is the tag being applied:
<@encode(base64)>hello</@encode>Anything that isn't a recognised operation is left alone and passed straight through as text, so stray <@ sequences in your data won't break the conversion.
The four operations
| Operation | Purpose |
|---|---|
<@encode(tag)>…</@encode> | Runs the tag's encode() method on the contents. |
<@decode(tag)>…</@decode> | Runs the tag's decode() method. Only tags that implement decoding offer this. |
<@decodeEncode(tag)>…</@decodeEncode> | Decodes the contents and wraps the result back up in an encode tag. Handy for taking an encoded value apart while keeping a recipe for putting it back together. |
<@autodecode>…</@autodecode> | Detects the encoding chain automatically and rewrites it as nested encode tags. |
Nesting tags
Tags evaluate from the inside out, so this base64-encodes the text and then URL-encodes the base64:
<@encode(urlEncode)><@encode(base64)>hello</@encode></@encode>Text either side of a tag is preserved, so you can encode just part of a payload:
<img src=x onerror=<@encode(htmlEntities)>alert(1)</@encode>>Arguments
Tags can take arguments, listed after the tag name and separated by commas. Four kinds are supported:
- Strings — single or double quoted, with
\n,\r,\t,\v,\f,\\,\xNNand\uNNNNescapes. An unclosed quote is an error. - Numbers — decimal (
42) or hexadecimal (0xff). - Quoteless strings — bare text, useful when the value contains no comma or bracket, e.g.
UTF-8. - Booleans —
trueorfalse.
<@encode(myTag,'a string',0xff,UTF-8,true)>input</@encode>When you insert a tag from the menu its arguments are filled in with their defaults, so you can see the shape immediately and edit from there.
Self-closing tags
Some tags generate output rather than transforming input — a random value, a timestamp, a variable lookup. These are marked self-closing and are written with a space, slash and closing bracket, with no closing tag:
<@encode(uuid) />The autodecoder
The autodecoder takes a blob of encoded data and works out how to get back to the original. It's available two ways: the Autodecoder panel under the converter, which runs continuously against whatever is in the input, and the <@autodecode> tag, which you can nest like any other tag.
Its output isn't the decoded text — it's the encoding chain, written as nested encode tags with the plaintext at the centre. So given a double-encoded value you might get back:
<@encode(url)><@encode(base64)>secret</@encode></@encode>This tells you both what was done to the data and how to reproduce it. Press ↑ Input in the panel to move that chain into the input; converting it gives you the original value back, and you can delete layers to peel the encoding apart.
How it decides, roughly:
- Whole-input match. Every installed tag that implements
matches()is tried in priority order (URL, gzip and deflate first, then base64, hex, unicode escapes, HTML entities and so on). Each candidate decode is scored: gaining structure (JSON, XML/HTML, JWT, UUID, a URL, a path) scores highly, as does falling entropy, shrinking length, recognisable binary magic bytes, and output that another tag'smatches()recognises as a further layer. Highest score wins. - Speculative decode. If nothing matched but the input is dense with encoding markers — lots of
%or backslashes, URL-encoded escape sequences, a UTF-7 shift character — it tries the obvious candidates anyway. This is what catches double and triple URL encoding, where the outer layer doesn't look like a clean single encoding. - Inline matches.Failing that, it scans the input left to right looking for embedded encodings using each tag's
startsWith(), with word-boundary checks so ordinary words aren't mistaken for hex or base64. - Recurse. Whatever it decodes is fed back in, up to 20 layers deep.
Because the scoring uses the matches() methods of all your installed tags, installing more tags makes the autodecoder better at recognising layers — and a tag you write yourself joins in automatically as soon as you give it a matches() or startsWith() method.
Finding and installing tags
The tag store lists every published tag. Scroll to load more, or use the search box in the header — it matches tag names and descriptions. Each card shows the category, the author, and how many installs, likes and views the tag has.
Open a tag to see its full source, its arguments, its encoding tests, and buttons to Install tagand like it. Installing is what makes a tag appear in the converter's tag menu, in autocomplete, and in the autodecoder's detection pass. Tags marked Built-in are always available and don't need installing.
Your own installs live under My tags in the avatar menu, alongside My tests, My urls and My HackPads.
Encoding tests
Encoding tests are community-submitted proofs that a conversion behaves correctly. They run in your browser, in the same sandbox the converter uses. There are two kinds:
- Autodecode test — give an encoded input and the exact tag chain the autodecoder should produce for it. This is how you pin down detection behaviour and catch regressions when new tags change the scoring.
- Tag test — pick a tag, an operation (
encodeordecode), optional arguments and an input, and record the expected output.
The index page has a batch runner that runs every listed test and reports passes and failures; individual tags show their own tests on their page. Tests are immutable once created, so a passing test stays meaningful. Names are limited to 100 characters, descriptions to 500, and inputs and expected outputs to 10,000.
You can jump straight from a tag to /encoding-tests/new?tagId=… to write a test for it with the tag pre-selected.
HackPad
HackPad runs HTML and JavaScript in a throwaway sandboxed iframe so you can test payloads without a target. It has two input panes — JS and HTML — each with its own output pane, plus a Render panel showing the live document.
Press Execute or Ctrl+Enter to run. Whatever your JS evaluates to appears in the JS output; the serialised DOM after execution appears in the HTML output. Calls to alert() are detected and flagged, which is what the hacking room uses to tell you a payload fired.
The Options panel is where the interesting controls live:
| Option | Effect |
|---|---|
| Sandboxed? | On by default. Turning it off asks for confirmation and shows a permanent warning — without the sandbox, code you run has the origin's privileges, so never do it with untrusted input. |
| Content Type | text/html, application/xhtml+xml or image/svg+xml. The document wrapper changes to match, so you can test parser differences. |
| Mode | HTML renders normally. MXSS re-serialises the document through innerHTML after parsing, which is how you surface mutation XSS. |
| Charset | Sets the document's meta charset across a long list of legacy encodings. Picking UTF-16BE or UTF-16LE also encodes the surrounding document, so charset-confusion tricks behave as they would on a real page. |
| Auto execute? | Re-runs on every keystroke. |
| CSP | Injected as a meta http-equiv policy, for testing bypasses against a specific policy. |
Save stores the HackPad and gives it a shareable URL, Copy as HTML copies the HTML pane as rich text, and JS → Snippet / HTML → Snippet hand the code to the image editor. A HackPad History panel keeps your recent runs, and a collapsible Converter at the bottom of the page gives you the full tag interface without leaving HackPad.
The hacking room
The hacking room is a shared HackPad. It answers the question “does this payload work in yourbrowser?” without asking anyone to copy and paste.
- Press
Generate new roomto mint a room, thenCopy to clipboardand send the link to whoever you want in it. Room IDs are random UUIDs; anyone with the link can join, so treat the link as the secret. - Everyone picks a username on joining. The Connected browserspanel lists who's present along with their detected browser and version.
- Type HTML into the HackPad and it's broadcast to everyone in the room. Each browser runs it in its own sandbox and sends back what it rendered, plus whether
alert()fired. - The HTML output panel collects those results side by side, so browser differences are immediately visible.
- The Messages panel is a simple chat for coordinating.
Broadcast HTML is capped at 10,000 characters and chat messages at 1,000.
Saving and sharing
Save in the converter offers two visibilities:
- Private— your input is base64-encoded into the page's URL fragment. Nothing is sent to the server; the data lives entirely in the link, so anyone you send it to sees exactly what you had. This is the only option when you're not logged in.
- Public — requires a login and a description, and creates a permanent page under
/urls/<id>. Public URLs record which tags were in play, so anyone opening the link gets those tags available for that conversion even if they haven't installed them.
Browse everyone's saved work at URLs and HackPad URLs, or your own via My urls and My HackPads in the avatar menu. The site footer also surfaces the most popular and most recent URLs, HackPads, tags and users.
Snippet
Snippet turns code into a presentable image — for a writeup, a slide or a tweet. It's the destination of the Send to Snippet buttons in the converter and HackPad, which pass the code across in the URL fragment.
You get syntax highlighting for JavaScript, TypeScript, HTML, CSS, JSON, Python, Markdown, Go, Rust, SQL, Java, PHP, YAML and a mixed HTML/JS/CSS mode, plus control over the gradient background, font and size, code theme and background, border, line numbers, title bar and text, padding and drop shadow. The Highlight panel emphasises a line range in a colour of your choice.
Presentation preset and 𝕏 Twitter preset set sensible dimensions and type sizes in one click; you can also name and save your own presets, which are stored in your browser. Finish with Copy image or Export PNG.
Profiles and community
Every tag has an author, and every author has a profile listing their saved URLs and HackPads. You can follow people and like tags; profiles show whether you follow each other. Tag pages show install counts, likes and views, which is a decent proxy for what's worth installing.
Tips
- Install tags before anything else — the converter, autocomplete and the autodecoder are all only as good as the tags you have.
- Reach for the autodecoder before decoding by hand. Even when it's not completely right it usually identifies the outer layer, and
↑ Inputgets you a chain you can edit. - If a tag isn't applying, hit
Debug— the parse tree shows immediately whether the tag was recognised or treated as text. - Watch the red byte counter and the red character highlighting. They're often the fastest way to spot a smuggled invisible character or a homoglyph.
- Select a single character to get its full encoding table in the bottom-right panel — no need to convert just to find a codepoint.
- Turn off real-time conversion when working with compression, hashing or very large inputs.
- In HackPad,
Ctrl+Enterexecutes from either editor. - When you write a tag, give it
matches()andstartsWith()— it costs a couple of regexes and it teaches the autodecoder a new encoding. - Back new tags with an encoding test. It documents the behaviour and the batch runner will catch it if something later breaks it.