Hex to Decimal Converter

Convert between hexadecimal, decimal and binary, with big-integer support for full 256-bit Ethereum values. Type into any field to update the others.

8-bit value, fits in 1 byte.

Hex, decimal and binary

The same integer can be written in different bases. Hexadecimal (base 16) is compact and maps cleanly onto bytes, which is why Ethereum uses it for addresses, hashes and calldata. Decimal (base 10) is how humans usually read numbers, and binary (base 2) is what the machine works in.

Two hex characters encode one byte. A 32-byte word, the EVM's native size, is 64 hex characters, or a 256-bit binary number. This converter keeps full precision across all three so nothing is rounded.

Two hex encodings, and why nodes mix them

The JSON-RPC spec defines two different hex encodings and uses both in the same response object, which is the single most confusing thing about reading raw node output.

QUANTITY is for numbers. It is written in its shortest form with no leading zeros, so seventeen is 0x11, a block number is 0x10d4f, and zero is the special case 0x0 rather than an empty string. Block numbers, balances, gas, nonces and chain IDs all use it.

DATA is for byte arrays. It always has an even number of digits and keeps every leading zero, because the length is part of the value: a 32-byte hash is always 64 characters even if it begins with a run of zeros. Hashes, addresses, calldata, log topics and contract bytecode all use it.

{
  "number":     "0x10d4f",       // QUANTITY, no padding      -> 68943
  "gasUsed":    "0xb2f1c",       // QUANTITY                  -> 732956
  "hash":       "0x00a3f1...",   // DATA, 32 bytes, padding kept
  "address":    "0x00000000219ab540356cbb839cbe05303d7705fa"
                                 // DATA, 20 bytes: the beacon deposit
                                 // contract, whose leading zero bytes
                                 // survive precisely because it is DATA
}

The practical consequence: never compare a quantity as a string. A node may hand you 0x1 where your fixture says 0x01, and both mean one. Parse to a bigint, then compare. The eth_getBlockByNumber reference lists which field uses which encoding.

Decoding a 32-byte word

ABI-encoded return values, storage slots and log data all come back as a sequence of 32-byte words, and each type sits in that word differently. Getting this wrong is the usual reason a decoded value looks like an astronomically large number.

// uint256: the whole word, big-endian
0x0000000000000000000000000000000000000000000000000de0b6b3a7640000
BigInt(word)                       // 1000000000000000000n  (1 ETH)

// address: 20 bytes, right-aligned, 12 zero bytes of padding
0x00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa
"0x" + word.slice(-40)             // strip the padding

// bool: zero is false, anything else is true
0x0000000000000000000000000000000000000000000000000000000000000001

// bytes32 / hashes: the word IS the value, keep every zero

Signed integers use two's complement, so a small negative number arrives as a word full of leading f characters. Convert by checking the top bit and subtracting 2^256 when it is set:

const TWO_256 = 1n << 256n;

function toInt256(word) {
  const v = BigInt(word);
  return v >= TWO_256 / 2n ? v - TWO_256 : v;
}

toInt256("0xff...fd"); // -3n  (a negative tick, a signed delta, ...)

In production, reach for the ABI decoder rather than slicing strings: AbiCoder.defaultAbiCoder().decode() in ethers.js, decodeAbiParameters in viem. Hand-decoding is for the moment when the decoder disagrees with you and you need to see the bytes. That moment usually starts with an eth_call response you did not expect, and ends with the value converted back to ether in the wei converter.

Frequently asked questions

How do I convert hex to decimal?

Type a hex value (with or without the 0x prefix) into the Hexadecimal field. The decimal and binary equivalents update instantly.

Does it handle 256-bit Ethereum values?

Yes. The converter uses native BigInt, so it handles full 256-bit words like uint256 balances and storage slots without losing precision.

Why does my hex have a 0x prefix?

0x marks a value as hexadecimal, the convention across Ethereum and most programming languages. You can paste values with or without it here.

Why does the node return 0x1 instead of 0x01?

Because JSON-RPC quantities are encoded with no leading zeros. Numbers come back in their shortest form, so a block number is 0x10d4f and not a padded 32-byte word. Byte arrays follow the opposite rule and keep every leading zero, since there the length is the meaning.

How do I read an address out of a 32-byte word?

Addresses are 20 bytes right-aligned inside a 32-byte word, so the first 24 hex characters after 0x are zero padding. Take the last 40 characters and prefix them with 0x, then run the result through an EIP-55 checksum before showing it to anyone.

Are negative numbers supported?

This tool works with non-negative integers, which covers addresses, hashes, calldata words and unsigned integers. For signed values, convert the two's-complement word first; the section above explains how.

Where these 32-byte words come from

Storage slots, calldata and log data all arrive as hex words from eth_call, eth_getStorageAt and eth_getLogs. Decoding them is free; pulling them at volume is what costs you, in latency on every call and in compute units on the invoice.

eth_call reference