IG網址代碼還原成數字後右移23位、加上epoch 1314220021721毫秒,就是發布時間;網路常見的22位會算錯好幾年(出處:Instagram Engineering 官方部落格〈Sharding & IDs at Instagram〉,查證日期 2026-09-21)。
先前在一場社群抽獎活動裡要判斷一則IG貼文是不是臨時發的,還是有人拿舊貼文重貼灌分,我當場用位移公式把網址代碼換算成時間,四條真實網址都對得上,其中一條算出12:31發布,參加者12:33貼進群組,差2分鐘。
回頭整理這個方法要不要寫成文章時才發現,網路上不少教學把公式寫成右移22位,但我自己那次用的是23位。同一條公式,位移數字差1,算出來的年份可以差到9年,這個落差值得攤開來講清楚。
先講機制。Instagram Engineering官方部落格2011年發過一篇「Sharding & IDs at Instagram」,原文寫得很直接:
Each of our IDs consists of: 41 bits for time in milliseconds, 13 bits that represent the logical shard ID, 10 bits that represent an auto-incrementing sequence, modulus 1024.
64位的ID裡,最高41位是時間戳(毫秒),接下來13位是shard編號,最後10位是流水號。13加10等於23,這就是要位移的位數,不是22。
貼文網址裡看到的那串代碼,是這個ID用base64轉成的可讀版本,字母表是A到Z、a到z、0到9、再加-和_,剛好64個字元對應64進位。換算成程式碼,10行內:
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
const code = 'CGGOHDXhhK-';
let id = 0n;
for (const ch of code.slice(0, 11)) id = id * 64n + BigInt(ALPHABET.indexOf(ch));
const publishedAt = new Date(Number((id >> 23n) + 1314220021721n));
console.log(publishedAt.toISOString());
查證日期2026-09-21,實際跑一次驗證。上面這則CGGOHDXhhK-不是我自己的貼文,是ODU研究團隊2021-02-20那篇部落格文章裡公開引用的樣本,那篇文章當時直接從Instagram的頁面原始碼裡讀到這則貼文的media id是2415680307434230462、發布時間顯示為2020-10-08T21:12:34Z。拿這組已知答案回頭驗證我的公式:
shortcode CGGOHDXhhK-還原成id後右移23位,算出2020-10-08T21:12:34.952Z;Instagram頁面本身顯示的發布時間是2020-10-08T21:12:34Z,兩者差0.952秒。同一組id右移22位,算出2029-11-23T21:18:08Z,差了9年。
用程式碼跑出來的原始輸出:
decoded id: 2415680307434230462
match: true
shift23 date: 2020-10-08T21:12:34.952Z
shift22 date: 2029-11-23T21:18:08.183Z
actual (IG頁面顯示的發布時間): 2020-10-08T21:12:34Z
這個9年的落差不是隨機誤差,是可以算出來的固定倍率。少位移一位,等於少丟掉一個bit,換算出來的「距離epoch的毫秒數」會接近變成兩倍,離Instagram的2011年epoch越遠的貼文,位移錯一位造成的偏移就越大。這則貼文離epoch約9.13年,兩倍是18.25年,2011年加18.25年正好落在2029年11月,跟實際算出來的2029-11-23完全對上。2026年發的貼文用22位算,會直接跳到2041年。
網路上會出現22這個數字,常見原因是通用的Snowflake ID教學。Twitter的ID結構是41位時間戳加10位機器碼加12位序號,10加12剛好是22位,很多教學文章把這條公式當成所有Snowflake類ID的通用寫法,套到Instagram時沒注意到IG的欄位配置是13加10,不是10加12。
準確度要分兩種情況講清楚。同一篇ODU研究團隊的部落格文章抽樣1,000則貼文比對,76.4%的貼文,用media id算出來的時間跟頁面上顯示的發布時間誤差都在1到2秒內,其中輪播貼文的落差多半落在1秒或2秒,跟我這次驗證的0.952秒是同一個量級。但1000則裡有23.6%落差較大,這些剛好都是單支影片貼文,落差最大到60分32秒,因為影片類型的貼文是先上傳處理、media id先被建立,隔一段時間才真正發布上線,兩個時間點本來就不是同一刻。所以這個方法拿來查照片、輪播貼文很準,拿來查Reels發布時間,數字可以當參考,不能當成精確到秒的證據。
FB做不到同樣的事。FB現在的貼文網址是pfbid開頭的不透明字串,裡面沒有可解的時間資訊,只能登入後台或靠人工看畫面判斷。
要講清楚這整個方法在做什麼:從頭到尾只是把公開網址裡的那串代碼換算成數字再做位元運算,不需要登入任何帳號、不呼叫Instagram的任何API、也不用抓取或打開那則貼文的頁面。網址本身是公開的,代碼本身也是公開的,這裡做的事只是照Instagram官方公開過的ID欄位設計,把代碼還原成它原本包含的時間資訊。
套公式前先拿已知答案驗一次。