uniqid
Generates a 13- or 23-character time-based identifier, optionally with a prefix.
uniqid(string $prefix = "", bool $more_entropy = false): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$prefixoptional | string= "" | A string prepended to the identifier. Useful when several hosts may generate identifiers in the same microsecond. |
$more_entropyoptional | bool= false | When true, appends extra random data, making a collision less likely and the result 23 characters instead of 13. |
Return value
stringA timestamp-based identifier: 13 hexadecimal characters with an empty prefix, or 23 characters when more_entropy is true, plus the length of any prefix.
uniqid builds an identifier from the current time: eight hex digits of Unix seconds followed by five hex digits of microseconds. With more_entropy set it appends a random decimal fraction, giving 23 characters. Within a single PHP process it busy-waits until the microsecond changes, so two consecutive calls always differ.
What it is good for
Scratch filenames, cache-busting suffixes, correlation IDs in logs, and human-facing reference numbers where a duplicate is an annoyance rather than a security problem. Because it is time-ordered, sorting a list of uniqid values sorts them roughly chronologically, which is genuinely useful for log correlation.
What it is not good for
Anything an attacker benefits from guessing. The value is essentially a timestamp, so password reset tokens, session IDs, API keys, invite codes and unguessable URLs must not use it — someone who knows roughly when you generated it can enumerate the small remaining space. Use random_bytes with bin2hex instead.
The uniqueness guarantee is also per-process, not global. Two PHP-FPM workers, two containers or two servers can hit the same microsecond and produce identical values, which is what the prefix parameter is for.
Example
When to use it
- Name a temporary file in a scratch directory so concurrent requests do not collide
- Generate a request or correlation ID to tie log lines from one request together
- Append a cache-busting suffix to an asset URL after a rebuild
- Create a human-readable order or invoice reference with a per-host prefix
Frequently asked questions
Is uniqid actually unique?
Only within a single PHP process, where it waits for the microsecond to tick before returning. Separate processes, workers or servers can produce the same value in the same microsecond, so pass a per-host prefix or set more_entropy to true.
Can I use uniqid for a password reset token or session ID?
No. The value is a hexadecimal timestamp, so it is predictable to anyone who knows roughly when it was generated. Use bin2hex(random_bytes(32)) for anything that must be unguessable.
What is the difference between uniqid() and uniqid('', true)?
more_entropy appends extra random data, making the result 23 characters instead of 13 and collisions far less likely. It still is not cryptographically secure, because the leading timestamp is unchanged.
More examples
A safe temporary filename
The prefix keeps the file recognisable while uniqid keeps concurrent requests from clobbering each other's exports. This is a legitimate use because a filename collision is an operational bug, not a security hole - the file is deleted immediately and its name never guards anything.
<?php
$name = 'export_' . uniqid() . '.csv';
file_put_contents($name, "id,total\n1,42\n");
echo $name, "\n";
echo file_get_contents($name);
unlink($name);
echo 'Cleaned up: ', var_export(file_exists($name), true), "\n";Why uniqid must not be a security token
The uniqid value decodes straight back to its creation time, leaving roughly a million candidates an attacker can brute-force in seconds. bin2hex(random_bytes(16)) gives 128 bits with no structure at all, which is what a reset token or session ID needs.
<?php
$token = uniqid();
echo "uniqid token: $token\n";
echo 'Created at: ', date('c', hexdec(substr($token, 0, 8))), "\n";
echo "Only 5 hex digits (about 1M values) of the tail are unknown.\n\n";
$secure = bin2hex(random_bytes(16));
echo "random_bytes: $secure\n";
echo 'Unguessable bits: 128', "\n";
Discussion