MongoDB ObjectId ↔ timestamp converter

Extract the creation date hidden in any MongoDB ObjectId, or generate min/max ObjectIds from a date to run _id range queries — no driver, no shell, all in your browser.

epoch timestamp shortcuts

ObjectId → timestamp

date / timestamp → ObjectId

Only the first 4 bytes of an ObjectId encode time (seconds, UTC). Use min as an inclusive lower bound and max as an inclusive upper bound for _id range queries.

MongoDB _id range queries

How does an ObjectId encode time?

A MongoDB ObjectId is a 12-byte identifier, written as 24 hex characters, and only its first 4 bytes encode time: a big-endian count of seconds since the Unix epoch (00:00:00 UTC, 1 January 1970). The remaining 8 bytes are a random per-process value and an incrementing counter, which keep ObjectIds created in the same second unique — such ObjectIds share their first 8 hex characters but differ in the rest. Precision is one second; milliseconds are not stored. The timestamp records when the ObjectId was generated, usually the moment the document was inserted — MongoDB drivers generate ObjectIds client-side by default, so the encoded time comes from the client's clock, not the server's. Because the timestamp sits in the most significant bytes, ObjectIds sort roughly by creation time: one created in a later second always compares greater, but within the same second the order follows the random value and counter, not the exact moment — and ObjectIds from clients with skewed clocks can sort out of order. Second-level ordering is all that date-based _id range queries need, so they work without a separate createdAt field.

Querying _id by date

Because ObjectIds compare by their timestamp prefix first, you can filter a collection by creation date without a separate createdAt field. Generate the min ObjectId (timestamp + 16 zeros) for the start of your range and the max ObjectId (timestamp + 16 fs) for the end, then query { _id: { $gte: ObjectId("<min>"), $lte: ObjectId("<max>") } }. Min is an inclusive lower bound and max an inclusive upper bound. The range queries card above writes these filters for you — last 15 minutes, today, yesterday, older than 30 days or any custom window — for mongosh, the Node.js driver and PyMongo.