LogicGates.org Open the simulatorSimulator

Snowflake ID decoder

Paste a Discord or Twitter/X ID to see the moment it was made, to the millisecond, and the worker and sequence bits beside it. Or type a date to get the range of snowflakes from that moment.

A user, message, server or channel ID: in Discord, turn on Developer Mode and choose Copy ID. Up to 20 digits.

Made at, UTC 2016-04-30T11:18:25.796Z
Your time
…
Age
…
Unix ms
1462015105796

Working: shift right by 22, add the epoch

175928847299117063 >> 22 = 41944705796
41944705796 + 1420070400000 = 1462015105796
= 2016-04-30T11:18:25.796Z

Shifting right by 22 drops the low 22 bits, leaving the milliseconds since the Discord epoch, 2015-01-01T00:00:00.000Z. Adding the epoch gives Unix milliseconds.

The bits

bits 63 to 32
bits 31 to 0
Bit layout of the snowflake: each field, what it means, its bits and its value
Field Bits Value
Milliseconds since the Discord epoch41944705796 ms after the epoch: 2016-04-30T11:18:25.796Z 63–22 (42) 41944705796
Internal worker ID1 21–17 (5) 1
Internal process ID0 16–12 (5) 0
Increment7, goes up by one for every ID generated on that process 11–0 (12) 7

As a JavaScript number this becomes 175928847299117060, which is a different ID: numbers above 2^53 lose their last digits, which is why APIs send snowflakes as strings.

Date to snowflake

For example 2024-03-01, 2024-03-01 18:30 or 2024-03-01T18:30:00+01:00. Uses the Discord layout chosen above.

Snowflakes made at 2016-04-30T11:18:25.796Z
First 175928847298985984
Last 175928847303180287

Every Discord ID made in that millisecond lies between these two: the time in the top bits, and the low 22 bits all 0 for the first and all 1 for the last. Use the first as an after value or the last as a before value to page through messages by time.

How a snowflake ID works

A snowflake is a 64-bit number that a server can make on its own, without asking a central database for the next number, and that still sorts in time order. Twitter designed it in 2010, and Discord uses the same idea. The top bits are the milliseconds since the service's epoch; below them are bits that say which machine made the ID, and a counter for IDs made by that machine in the same millisecond.

Because the time is in the top bits, a bigger ID is always a later one (to the millisecond), so sorting IDs sorts by age. The same Discord example, worked through:

175928847299117063 >> 22 = 41944705796
41944705796 + 1420070400000 = 1462015105796
= 2016-04-30T11:18:25.796Z

The same sum in code. BigInt keeps all 64 bits; a plain number would not.

// JavaScript
const snowflake = '175928847299117063';
const ms = Number(BigInt(snowflake) >> 22n) + 1420070400000;
new Date(ms).toISOString();

# Python
from datetime import datetime, timezone
snowflake = 175928847299117063
datetime.fromtimestamp(((snowflake >> 22) + 1420070400000) / 1000, tz=timezone.utc)
Discord and Twitter/X layouts
Service Epoch Fields, top bits first (width) Runs out
Discord 2015-01-01T00:00:00.000Z
1420070400000
Milliseconds since the Discord epoch (42), Internal worker ID (5), Internal process ID (5), Increment (12) 2154-05-15
Twitter/X 2010-11-04T01:42:54.657Z
1288834974657
Sign bit (1), Milliseconds since the Twitter epoch (41), Machine ID (10), Sequence (12) 2080-07-10

Discord snowflakes by year

The first possible Discord ID of each year. Any ID smaller than a year's value was made before that year began, so you can date an ID roughly at a glance.

From First snowflake
2015-01-01 0
2016-01-01 132271570944000000
2017-01-01 264905529753600000
2018-01-01 397177100697600000
2019-01-01 529448671641600000
2020-01-01 661720242585600000
2021-01-01 794354201395200000
2022-01-01 926625772339200000
2023-01-01 1058897343283200000
2024-01-01 1191168914227200000
2025-01-01 1323802873036800000
2026-01-01 1456074443980800000
2027-01-01 1588346014924800000

Common mistakes

  • Parsing the ID as a number. In JavaScript, Number("175928847299117063") gives 175928847299117060. The last digits are gone because the value is past 253, the limit of exact integers in a double; the integer limits page lists where each type runs out. Keep IDs as strings and use BigInt for arithmetic.
  • Using the wrong epoch. A Discord ID read from the Unix epoch lands in the 1970s or 1980s, and one read with Twitter's epoch comes out about four years too early. Switch the service above to see the difference.
  • Dividing instead of shifting in a language with floats. id / 4194304 in floating point rounds; shift right by 22 on a 64-bit integer, or divide with integer division.

To see an ID as the 64 bits it is, paste it into the binary converter. Snowflakes are one of several IDs with a time inside; UUID version 7, ULIDs and MongoDB ObjectIds are decoded by the UUID decoder.

Questions

How do I get the date from a Discord ID?

Shift the ID right by 22 bits, which is the same as dividing by 4,194,304 and dropping the remainder, then add Discord's epoch, 1420070400000. The result is milliseconds since 1970. For 175928847299117063 that is 41944705796 + 1420070400000 = 1462015105796, which is 2016-04-30T11:18:25.796Z.

What is the Discord epoch?

2015-01-01T00:00:00.000Z, the first moment of 2015, which is 1420070400000 in Unix milliseconds. Discord IDs count from there rather than from 1970 so that the 42 timestamp bits last longer: until 2154-05-15T07:35:11.103Z.

Why are snowflake IDs sent as strings?

JavaScript numbers only hold whole numbers exactly up to 2^53, and snowflakes go past that. Read as a number, 175928847299117063 becomes 175928847299117060, a different ID. Discord's and Twitter's APIs send them as strings so nothing is lost; use BigInt to do arithmetic on them.

How do I find Discord messages from a particular date?

Turn the date into a snowflake and use it as the before or after value in Discord's API, which accepts any snowflake there, not only real message IDs. The date to snowflake box on this page gives the smallest and largest snowflake for a moment.

Can two snowflakes be the same?

Two different objects should not get the same one: each worker and process has its own ID bits, and the increment goes up for every ID that process makes. Discord's documentation notes one exception on purpose: some child objects share their parent's ID, such as a server's @everyone role, which has the server's ID. In Twitter's original design the 12-bit sequence starts again from 0 each millisecond, so one machine can make 4,096 IDs per millisecond.

Is a Twitter/X ID decoded the same way?

The same shift by 22, but with Twitter's epoch, 1288834974657 (2010-11-04T01:42:54.657Z). The 10 bits below the time are a machine ID rather than Discord's worker and process, and the top bit is kept 0 so the ID is positive as a signed 64-bit number. Tweets from before late 2010 have older, sequential IDs that hold no time.