String to Hex Converter_
Hex is what you find, not what you write. Nobody sets out to convert a sentence into hexadecimal — they have a hexdump, a packet capture, a BLOB column or a config value, and they want to know what it says. So the work is not the arithmetic. It is accepting the hex in whatever shape it turned up in.
And the shape tells you where it came from. 0x48 is a source literal, \x48 a string escape, %48 came out of a URL, 48-65 off a Windows registry export, and a block with offsets down one side and printable characters down the other is xxd. This reads all of them, and says which one it saw.
- Input
- Hex in any common notation — prefixed, escaped, percent-encoded, colon or hyphen separated, or a whole xxd or hexdump -C block with its offsets and gutter. Or text, in the other direction.
- Output
- The decoded text, or the bytes in whichever notation you need — including a full xxd-style dump.
- Processing
- Decoded in this tab. Invalid sequences fail loudly with the reason rather than producing replacement characters.
- Limits
- It works on bytes, so it cannot tell you what a byte sequence means in a format it does not know. A BLOB that is a JPEG will decode to nothing readable, correctly.
- Why an odd number of digits is refused
- Hex is read in pairs, so `abc` is either 0a bc or ab c0 — a leading zero that was dropped, or a trailing one. Those are different bytes and there is no way to tell which was meant. Tools that guess are right about half the time, so this asks instead.
The notation tells you where the bytes came from
Ten shapes, one meaning
The same three bytes can arrive as 486921, 48 69 21, 0x48 0x69 0x21, \x48\x69\x21, %48%69%21, 48:69:21 or 48-69-21. None of that is decoration: a 0x prefix means somebody printed a byte array from code, percent signs mean it passed through a URL, colons mean a MAC address or a certificate fingerprint, hyphens mean Windows. Knowing which is which tells you what you are holding before you have decoded a single byte of it.
A hexdump is not just hex
Paste xxd output into most converters and you get nonsense, because a dump has three columns: an offset on the left, the bytes in the middle, and a printable gutter on the right. The offset is not data. The gutter is not data — and it is the harder of the two, because it is text that can itself look like hex. A dump of the word deadbeef has deadbeef sitting in the gutter, and a converter that strips by pattern rather than by position will read it as eight more bytes.
Two notations are not bytes at all
H is a UTF-16 code unit and H is a Unicode code point. Neither is a byte. Below U+0080 all three views coincide, which is why treating them as interchangeable appears to work and then stops: é is code point U+00E9, one UTF-16 unit 00e9, and two UTF-8 bytes c3 a9. Three different numbers for one character, and only the last is what a byte-oriented tool should hand you.
An odd number of digits has no honest answer
Hex is read two digits to a byte, so an odd count means a digit is missing — and nothing in the string says which end. abc is 0a bc if a leading zero was dropped and ab c0 if a trailing one was. Different bytes, different text, and a fifty per cent chance either way. Most converters pad silently in whichever direction their author preferred; this refuses and says why, because a wrong answer that looks right is worse than no answer.
The encoding decides what the bytes say
c3 a9 is é read as UTF-8 and é read as Latin-1. Both readings are correct; only one matches what was written. This is the whole of mojibake — bytes encoded one way and read another — and it is why a converter that assumes UTF-8 without saying so will occasionally hand you something confidently wrong. Where the bytes are not valid in the encoding you picked, this says so rather than filling the gaps with replacement characters, because that failure is information.
Hex is not encryption, and not compression
It is a way of writing bytes that survives being pasted anywhere, at a cost of exactly double the size. Anything hex can hide, a glance can reveal — it is the format of choice for a value that must pass through a text field intact, and no protection whatsoever for a value that must stay private. Base64 does the same job at four bytes for every three rather than two for one, which is why hex survives where readability matters and base64 where size does.
Paste it in whatever shape you found it
- 01Leave it on Hex → Text if you are reading something. That is the direction almost everyone needs.
- 02Paste the hex exactly as you found it — prefixes, separators, or a whole xxd block. Nothing needs cleaning up first.
- 03Read the note under the output. It names the notation and what produces that shape, which is often the fastest way to work out what you are looking at.
- 04Change the encoding if the text comes out wrong rather than empty. Bytes that decode to mojibake are usually Latin-1 or UTF-16, not broken.
- 05Swap the direction to go the other way, and pick an output notation that suits where it is going.
A hexdump pasted straight in
Most converters read the offsets and the printable gutter as data and return nonsense twice the length it should be.
00000000: 4865 6c6c 6f21 Hello!
Hello! The offset and the gutter are stripped by position, not pattern.
A BLOB from a database
A column stored as hex, with no separators and no clue about the encoding until you look at the bytes.
0x48656c6c6f2c20776f726c64
Hello, world Every byte below 0x80, so the encoding does not matter here.
Text that decoded to mojibake
The bytes are fine and the encoding is wrong. This is the whole of mojibake, and it is fixable by changing one dropdown.
c3a9 → é
c3a9 → é Both readings are correct. Only one is what was written.
A byte array for source code
The bytes are known and they need to go into C, Python or a shell script in the form that language expects.
Hello
{ 0x48, 0x65, 0x6c, 0x6c, 0x6f }
\x48\x65\x6c\x6c\x6f
%48%65%6c%6c%6fWhere each notation comes from
| Shape | Origin | Byte or not |
|---|---|---|
48656c | A checksum, a database BLOB, or anything stripped of separators | Bytes |
48 65 6c | A hex editor selection, or written out by hand | Bytes |
0x48 0x65 | A C, Python, Java or SQL literal — or a debugger printing an array | Bytes |
\x48\x65 | A string literal in C, Python, PHP, or a shell $'…' quote | Bytes |
%48%65 | A URL. Percent-encoding is bytes, which is why one accented character becomes several | Bytes |
48:65:6c | A MAC address, a certificate fingerprint, or OpenSSL | Bytes |
48-65-6C | A Windows registry export, or PowerShell | Bytes |
\u0048 | A JSON or JavaScript string | Code unit — UTF-16, not a byte |
H | HTML or XML source | Code point — not a byte |
| offsets + gutter | xxd, hexdump -C, or a hex editor | Bytes, with two columns that are not |
The last three are the ones that cause trouble. Below U+0080 a byte, a UTF-16 code unit and a code point are the same number, so mixing them up works until the first accented character.
Working with hex
- Say which encoding you mean when you ask someone for "the hex of" a string. There is no such thing without one — the same text is different bytes in UTF-8, UTF-16 and Latin-1.
- Suspect the encoding, not the data, when text decodes to mojibake. Bytes that produce é were almost certainly UTF-8 read as Latin-1.
- Keep the offsets when you save a hexdump. They are how you find the same place again, and any tool worth using will strip them for you.
- Prefer lowercase unless something requires otherwise. It is the convention nearly everywhere, and case-sensitive string comparison of checksums is a real source of false mismatches.
- Use base64 when size matters and hex when readability does. Hex doubles the length; base64 adds a third, and cannot be read by eye.
- Never treat hex as concealment. It is a transport encoding, reversible by anyone, and putting a secret in it protects nothing.
Where hex conversion goes wrong
The printable gutter gets read as data
A hexdump line ends in the text those bytes represent, and that text can look like hex. Stripping by pattern rather than by column silently doubles the output, and a dump of the word deadbeef is the case that proves it.
An odd digit count is padded silently
Converters that pad choose an end and do not tell you. Half the time the other end was meant, and the resulting bytes are wrong in a way nothing downstream will flag.
\u and &#x are not bytes
One is a UTF-16 code unit and the other a code point. They agree with bytes only below U+0080, so a conversion that treats them as bytes works on ASCII and breaks on the first accented character.
Replacement characters hide the real problem
A decoder that emits U+FFFD for invalid sequences turns a solvable question — which encoding is this? — into a corrupted string. The failure is the useful information.
Hex is not a security measure
It is reversible by inspection and it doubles the size of what it encodes. It exists so bytes can pass through text channels unharmed, not so they can pass unnoticed.
Notations, encodings and failure
- Notations read
- Continuous, space, colon and hyphen separated; 0x, \x, % and prefixes; \u escapes; and xxd or hexdump -C blocks with offsets and a printable gutter.
- Gutter handling
- Removed by column position — the first pipe, or the first run of two or more spaces — because the gutter is text that can itself look like hexadecimal.
- Encodings
- UTF-8, UTF-16 in both byte orders, Latin-1 and ASCII. TextEncoder only produces UTF-8, so the others are implemented directly.
- Odd digits
- Refused with the two possible readings shown. There is no correct guess.
- Invalid sequences
- Decoding is fatal rather than lossy: bytes that are not valid in the chosen encoding produce an explanation, never a replacement character.
- Unrepresentable characters
- Encoding to Latin-1 or ASCII fails, naming the character and its code point, rather than substituting a question mark.
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Questions about hex and text
How do I convert a string to hex?
Encode the text to bytes, then write each byte as two hexadecimal digits. The first step is the one that matters: the same string is different bytes in UTF-8, UTF-16 and Latin-1, so there is no hex of a string without an encoding — only the hex of its bytes.
Why does my hex have an odd number of digits?
Because a digit was lost, usually a leading zero that something trimmed. It cannot be repaired automatically: abc is either 0a bc or ab c0, and those are different bytes. Find where the string was trimmed rather than padding it and hoping.
How do I convert a hexdump to text?
Paste it whole. A dump has an offset column and a printable gutter that are not data, and both are stripped here by position — which matters, because a gutter can contain text that looks like hex.
Why does my decoded text look like é or ’?
That is mojibake: bytes encoded as UTF-8 and read as Latin-1. The data is intact and the encoding is wrong. Switch to UTF-8 and the characters come back — nothing is lost, and nothing needs repairing.
Is \u0048 the same as 48 in hex?
Only for characters below U+0080. \u is a UTF-16 code unit and hex here means a byte, and the two diverge as soon as a character needs more than one byte: é is code point U+00E9, one UTF-16 unit 00e9, and two UTF-8 bytes c3 a9.
What is the difference between hex and base64?
Both make bytes safe to paste anywhere. Hex uses two characters per byte and can be read by eye; base64 uses four for every three bytes and cannot. Hex where you will look at it, base64 where size matters.
Does converting to hex encrypt anything?
No. It is a way of writing bytes, fully reversible by anyone, and it doubles the length. It protects nothing — it only makes bytes survive a channel that expects text.
Why do I get an error instead of question marks?
Because the error is the useful answer. Bytes that are not valid in the encoding you chose mean the encoding is probably wrong, and replacing them with U+FFFD would destroy the evidence while looking like success.
Should hex be uppercase or lowercase?
Either is valid and lowercase is the wider convention. It matters when checksums are compared as strings rather than as values, which is a real and frequent source of false mismatches.
Is the data I paste here uploaded?
No. The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.