Signature
md5(string $string, bool $binary = false): stringPurpose
md5() turns a string of any length into a fixed-size fingerprint using the MD5 message-digest algorithm. The same input always gives the same digest, and even a tiny change in the input gives a completely different one. That makes it handy for non-security jobs such as building cache keys, labelling content for quick comparison, or matching checksums published by older systems.
It is not suitable for protecting passwords. MD5 is designed to be fast, which helps an attacker who tries billions of guesses. The manual warns against it for this purpose and points to password_hash() instead. MD5 is also unsuitable where an attacker could craft two different inputs with the same digest, such as signatures or integrity checks against a hostile party.
Signature
Parameters and defaults
$stringis the data to hash. PHP strings are byte sequences, so the digest depends on the exact bytes, including the encoding of any non-ASCII text.$binarydefaults tofalse. When it istrue, the digest comes back as raw binary instead of hexadecimal text.
Return value and failure cases
With the default $binary = false, you get a 32-character lowercase hexadecimal string. With $binary = true, you get a 16-byte string that is usually not printable.
The function has no "false on failure" result. It always returns a string. The only error situation is a type problem: passing a value that cannot be used as a string, such as an array, throws a TypeError. Under declare(strict_types=1), passing an integer where a string is expected is also rejected.
Example 1: hashing a known string
This mirrors the idea from the manual: the digest of apple is a well-known value.
$str = 'apple';
echo md5($str), "\n";1f3870be274f6c49b3e31a0c6728957f
The output is the 32-character hexadecimal digest followed by a newline.
Example 2: the empty string and a short word
MD5 is defined for empty input too, so md5('') is valid and returns a normal 32-character digest.
$hashes = [
'empty' => md5(''),
'hello' => md5('hello'),
];
echo json_encode($hashes, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);{"empty":"d41d8cd98f00b204e9800998ecf8427e","hello":"5d41402abc4b2a76b9719d911017c592"}Example 3: hexadecimal versus binary output
The binary form is the same 128-bit digest, only encoded differently. Use bin2hex() to convert it back to the text form.
$raw = md5('apple', true);
$hex = md5('apple');
echo json_encode([strlen($raw), strlen($hex), bin2hex($raw) === $hex]);[16,32,true]
Edge cases
- Empty string: it has a fixed, valid digest, so never treat a hash as "missing" just because the source was empty.
- Encoding matters: the same visible text saved as UTF-8 and as another encoding is a different byte sequence and gets a different digest.
- Binary output length: the raw result is always 16 bytes. Do not print it directly, store it in a text-only field or put it in JSON without encoding it first, because it can contain arbitrary bytes.
- Type coercion: in default (non-strict) mode, a number such as
123is converted to the string"123"before hashing. Be explicit with a cast when you want to make that obvious. - Case of the hex digits: PHP returns lowercase. If you compare against a checksum written in uppercase, normalise one side first.
Common mistakes
- Hashing passwords with md5(). Use
password_hash()to store them andpassword_verify()to check them. - Assuming a hash is encryption. A digest cannot be decrypted, and it does not hide short or guessable inputs from someone who simply hashes candidates.
- Comparing digests with
==in security-sensitive code. Loose comparison of strings can behave surprisingly when both look like numbers. Prefer===, orhash_equals()when comparing secret values to avoid timing leaks. - Treating the digest as unique. Distinct inputs can in theory share a digest, and deliberate collisions are practical for MD5. Do not use it as a trusted identity for untrusted data.
- Forgetting
$binary. Code that expects 16 bytes but receives 32 hex characters, or the reverse, will produce wrong keys or lengths.
Related functions
hash()computes many other digests, including stronger algorithms such as SHA-256.password_hash()andpassword_verify()are the right tools for passwords.hash_equals()compares two strings in constant time.sha1()andcrc32()are other fingerprinting helpers with different sizes and purposes.bin2hex()converts raw bytes, such as binary digests, to hexadecimal text.
Recap
md5() returns a deterministic 32-character hex digest of a string, or a 16-byte raw digest when $binary is true. It always returns a string and only throws for type errors. Use it for simple non-security fingerprints, choose hash() with a stronger algorithm when integrity matters, and never use it to store passwords.
Tested examples
$str = 'apple';
echo md5($str), "\n";1f3870be274f6c49b3e31a0c6728957f
$hashes = [
'empty' => md5(''),
'hello' => md5('hello'),
];
echo json_encode($hashes, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);{"empty":"d41d8cd98f00b204e9800998ecf8427e","hello":"5d41402abc4b2a76b9719d911017c592"}
$raw = md5('apple', true);
$hex = md5('apple');
echo json_encode([strlen($raw), strlen($hex), bin2hex($raw) === $hex]);[16,32,true]