UUID v1 Generator

Generate time-based UUID v1 with embedded timestamp

Format

Count:
Note:UUID v1 embeds the host MAC address and generation timestamp, which raises privacy concerns for most modern applications. For new projects, UUID v4 is recommended unless you specifically need time-ordered, decodable identifiers.

What is UUID v1?

UUID v1 is the original UUID version, standardised in RFC 4122 (2005). It generates unique identifiers by combining a high-precision timestamp with the MAC address of the generating host, plus a short clock sequence to handle sub-timestamp resolution.

Because the timestamp is embedded, UUID v1 values from the same host are monotonically increasing over time — making them naturally ordered. This was designed for distributed systems where each node could generate UUIDs independently without coordination.

Today UUID v1 is largely superseded by UUID v7 (sortable, no MAC leakage) and UUID v4 (fully random, private). It remains in use in systems like Apache Cassandra and legacy distributed databases.

Anatomy of a UUID v1

A UUID v1 string like 550e8400-e29b-11d4-a716-446655440000 encodes six distinct fields:

FieldSizeDescription
time_low32 bits32-bit low field of the 60-bit Gregorian timestamp (100-nanosecond intervals since Oct 15, 1582)
time_mid16 bitsMiddle 16-bit field of the 60-bit timestamp
time_hi_and_version16 bitsTop 12 bits of the 60-bit timestamp plus the 4-bit version number (always <code>1</code>)
clock_seq_hi_res8 bits6-bit clock sequence high field combined with the 2-bit RFC 4122 variant marker
clock_seq_low8 bitsLower 8 bits of the clock sequence
node48 bits48-bit node identifier — typically the MAC address of the generating network interface, or a random 48-bit value if no MAC is available

The clock sequence field (clock_seq_hi_res + clock_seq_low) is a 14-bit counter. It is incremented whenever the system clock moves backward (e.g. NTP adjustment) or when the system restarts without persisting the last known timestamp. This prevents duplicate UUIDs from being generated if the clock is not monotonically advancing.

Decoding the UUID v1 Timestamp

The 60-bit timestamp is scattered across three fields in the UUID. To reconstruct the generation time:

  1. Extract time_low (bytes 0–3), time_mid (bytes 4–5), and time_hi (bytes 6–7, minus the version nibble)
  2. Reassemble: (time_hi &lt;&lt; 48) | (time_mid &lt;&lt; 32) | time_low
  3. The result is a 60-bit count of 100-nanosecond intervals since October 15, 1582 (the Gregorian calendar epoch)
  4. Subtract the Gregorian-to-Unix offset: 122,192,928,000,000,000 (100-ns intervals between Oct 15 1582 and Jan 1 1970)
  5. Divide by 10,000 to convert 100-nanosecond intervals to milliseconds
  6. Use the result as a Unix millisecond timestamp to construct a Date object
  7. Format as ISO 8601 for human-readable output

The timestamp precision is 100 nanoseconds — far finer than UUID v7's millisecond precision. However, in practice most operating systems do not expose sub-millisecond clock resolution, so the lower bits are often zero or synthesised.

Privacy Concerns

The most significant drawback of UUID v1 is that it embeds the MAC address of the generating host in the node field. This means every UUID v1 carries a permanent, globally unique fingerprint of the machine that generated it.

An adversary who obtains a UUID v1 can determine: (1) the approximate time the ID was generated, (2) the MAC address of the generating host, and (3) by analysing multiple UUIDs, the rate at which IDs are being generated.

For this reason, UUID v1 should never be used as a public-facing identifier (e.g. in URLs or API responses) unless you are comfortable disclosing this information. RFC 4122 itself notes that a system may use a random 48-bit value instead of the MAC address, but many implementations do not.

When UUID v1 Is Still Appropriate

Apache Cassandra primary keys
Cassandra uses UUID v1 (via the TimeUUID type) as a core design pattern. The timestamp ordering maps naturally to Cassandra's storage model, enabling efficient time-range queries.
Legacy distributed systems
Systems built before UUID v7 existed (pre-2024) that rely on timestamp-ordered UUIDs and cannot easily migrate to a new format.
Audit and event logs
When the generation host identity is known and trusted, embedding the MAC address can provide additional traceability for audit events.
Internal identifiers
IDs that are never exposed outside a controlled internal system, where MAC address disclosure is not a concern.
Time-range queries without a separate timestamp column
The embedded timestamp can be decoded to filter rows by generation time, acting as a combined ID and timestamp.
Interoperability with older UUID v1 generators
When receiving or processing UUID v1 values from external systems that produce them, decoding the embedded timestamp for display or analysis.

UUID v1 vs UUID v7

UUID v7 is the modern successor to UUID v1 for time-ordered identifiers. Here is a direct comparison:

AspectUUID v1UUID v7
Epoch / Time BaseGregorian epoch (Oct 15, 1582)Unix epoch (Jan 1, 1970)
Precision100 nanoseconds1 millisecond
Node IdentifierMAC address (leaks host identity)Random (private)
PrivacyLeaks MAC address and generation timestampNo host information embedded
DB index performanceGood — sequential per hostExcellent — k-sortable across all generators
StandardRFC 4122 (2005)RFC 9562 (2024)

For new projects, UUID v7 is the recommended replacement for UUID v1. It provides similar time-ordering guarantees without the privacy implications of embedding the host MAC address.

Code Examples

UUID v1 generation is not available natively in browsers or Node.js. Use the uuid npm package:

JavaScript (browser)
// Generate a UUID v1 using the Web Crypto API
function generateUuidV1() {
  const buf = new Uint8Array(16)
  crypto.getRandomValues(buf)

  const ms = BigInt(Date.now())
  const gregorianOffset = 122192928000000000n
  const t = ms * 10000n + gregorianOffset

  const tLow   = Number(t & 0xFFFFFFFFn)
  const tMid   = Number((t >> 32n) & 0xFFFFn)
  const tHiVer = Number((t >> 48n) & 0x0FFFn) | 0x1000  // version 1

  const clockSeq    = (buf[8] & 0x3F) | 0x80  // variant 10xxxxxx
  const clockSeqLow = buf[9]

  const hex  = (n, pad) => n.toString(16).padStart(pad, '0')
  const node = [...buf.slice(10)].map(b => b.toString(16).padStart(2, '0')).join('')

  return `${hex(tLow,8)}-${hex(tMid,4)}-${hex(tHiVer,4)}-${hex(clockSeq,2)}${hex(clockSeqLow,2)}-${node}`
}

// Extract the embedded timestamp from a UUID v1
function extractTimestamp(uuid) {
  const parts = uuid.split('-')
  const tHex = parts[2].slice(1) + parts[1] + parts[0]
  const t = BigInt('0x' + tHex)
  const ms = (t - 122192928000000000n) / 10000n
  return new Date(Number(ms))
}

const id = generateUuidV1()
console.log(id)                      // e.g. "1eb5e8b0-6b4d-11ee-9c45-a1f2b3c4d5e6"
console.log(extractTimestamp(id))    // e.g. 2023-10-15T12:34:56.789Z
Python
import uuid
from datetime import datetime, timezone

# Generate UUID v1 (uses MAC address by default)
uid = uuid.uuid1()
print(uid)

# Extract embedded timestamp
# uuid.time is 100-ns intervals since Oct 15, 1582
GREGORIAN_OFFSET = 122192928000000000  # 100-ns intervals
ts_100ns = uid.time
ts_ms = (ts_100ns - GREGORIAN_OFFSET) // 10000
dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
print(dt.isoformat())   # e.g. "2023-10-15T12:34:56.789000+00:00"
Go
package main

import (
    "fmt"
    "time"

    "github.com/google/uuid"  // go get github.com/google/uuid
)

func main() {
    id, _ := uuid.NewUUID()  // UUID v1
    fmt.Println(id)

    // Extract timestamp from UUID v1
    // uuid.Time is 100-ns ticks since Oct 15, 1582
    t := id.Time()
    sec  := int64(t)/1e7 - 12219292800  // convert to Unix seconds
    nsec := (int64(t) % 1e7) * 100
    ts   := time.Unix(sec, nsec).UTC()
    fmt.Println(ts.Format(time.RFC3339Nano))
}

Frequently Asked Questions

Can I decode the timestamp from a UUID v1?
Yes. The generation timestamp is fully recoverable from a UUID v1 string. This tool does exactly that — paste any UUID v1 and it will display the decoded UTC timestamp. See the decoding steps above for the algorithm.
Is the MAC address always present in UUID v1?
Not necessarily. RFC 4122 permits implementations to substitute a randomly generated 48-bit value for the MAC address when no network interface is available or when privacy is desired. In practice, many server-side implementations do embed the real MAC address. Browser-generated UUID v1 values always use a random node value since browsers do not expose MAC addresses.
Why does the UUID v1 timestamp use 1582 as the epoch?
The Gregorian calendar reform took effect on October 15, 1582. The UUID v1 timestamp was defined relative to this date to provide a stable, universal reference point predating the Unix epoch (1970). This gives the 60-bit timestamp field enough range to remain unique until approximately 3400 AD.
UUID v1 vs UUID v7 — when should I still use v1?
The primary reason to use UUID v1 today is compatibility with existing systems — particularly Apache Cassandra, which uses v1 as its TimeUUID type. For all new systems, UUID v7 is strictly better: it uses the more familiar Unix epoch, has no MAC address leakage, and provides better B-tree index performance.
Can UUID v1 values collide?
In theory, two UUID v1 values can collide if the same MAC address generates two UUIDs within the same 100-nanosecond interval and the clock sequence is identical. The clock sequence exists precisely to prevent this — it is incremented on rapid successive calls. In practice, UUID v1 collisions are extremely rare in correctly implemented systems.