不離開面板就能預覽
以 Threads 官方的 658px 寬度載入原生卡片,高度自動貼合內容;也能切到「原始碼與中繼資料」。用 ← → 換篇,Esc 關閉。
Threadkeep 是免費開源的 Chromium 擴充功能:在貼文選單點「取得內嵌程式碼」,內嵌碼、內文、作者與發文時間就自動存進你的瀏覽器。
Threads 本來就有「取得內嵌程式碼」。擴充功能只在旁邊等著,對話框一出現,就把整篇貼文記下來。
在貼文右上角的「⋯」選單點「取得內嵌程式碼」,就是平常嵌入貼文的步驟。這是你唯一要做的事。
從對話框挑出完整的 <blockquote> 內嵌碼,再擷取內文、作者、發文時間與標籤,順手濾掉介面文字。
寫入 chrome.storage.local 並跳出「內嵌程式碼已儲存」。之後從工具列的彈出視窗或全頁控制面板都找得到。
按鈕、粉絲數與相對時間,常會混進擷取結果。下面直接執行擴充功能 content.js
裡的清洗函式:改動左邊的原始文字,右邊的清洗結果會即時更新。
這裡示範的是文字清洗階段。實際擷取時,擴充功能會先在頁面結構中排除時間標籤、作者連結與回覆區塊,再交給這一步處理。 查看 content.js 原始碼
工具列的彈出視窗適合快速查找,全頁控制面板負責預覽、批次處理與統計。收藏到數千篇,清單也是分批載入,打開與搜尋都不用等。
以 Threads 官方的 658px 寬度載入原生卡片,高度自動貼合內容;也能切到「原始碼與中繼資料」。用 ← → 換篇,Esc 關閉。
重複使用同一個背景分頁依序載入,不會一次開一堆分頁。可以暫停、繼續或取消;結果每 20 篇寫回一次,期間在 Threads 新存的貼文也不會被蓋掉。
刪除、批次刪除與清除全部之後,8 秒內按「復原」就還原;滑鼠移到提示上倒數就會暫停。
統計最常出現的 15 個標籤與作者,點一下就篩選,再點一次取消。
被刪除、轉私密或轉址的貼文會標成失效並記下原因,恢復後自動解除。
批次更新、複製 Embed 或刪除;三種匯出也只會帶走勾選的貼文。沒勾選時,這些按鈕保持停用,鍵盤也按不到。
搜尋會比對內文、作者、標籤,以及連結裡的帳號與貼文代碼。找出沒有內文、沒有發文時間或已失效的貼文,集中處理。
對話框會鎖定焦點,關閉後回到原本的按鈕;通知會被螢幕閱讀器念出來,滑鼠移上去就暫停倒數。深色模式可跟隨系統或在控制面板手動切換,也支援「減少動態效果」與 Windows 高對比模式。
有勾選就只匯出勾選的貼文,沒勾選就匯出目前篩選後的清單。三種格式都是能直接引用的 JavaScript
檔;每段內嵌碼附帶的
<script> 會先移除,網頁只需載入一次 embed.js。
const posts = [
'<blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@pinyu.daily/post/DQx7mK2pLsA" …>…</blockquote>',
'<blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@ocean.yuan_07/post/DQv3Rn8eTqB" …>…</blockquote>'
];
const posts = [
{
"embedCode": "<blockquote class=\"text-post-media\" …>…</blockquote>",
"postLink": "https://www.threads.com/@pinyu.daily/post/DQx7mK2pLsA",
"author": "pinyu.daily",
"content": "週末去台南吃了一輪,\n牛肉湯排了四十分鐘還是值得。…",
"tags": [
"台南",
"週末"
]
}
];
const posts = [
{
"embedCode": "<blockquote class=\"text-post-media\" …>…</blockquote>",
"postLink": "https://www.threads.com/@pinyu.daily/post/DQx7mK2pLsA",
"author": "pinyu.daily",
"content": "週末去台南吃了一輪,\n…",
"timestamp": "2026-09-22T12:41:00.000Z",
"timestampTitle": "2026年9月22日星期二 下午8:41",
"savedAt": "2026-09-23T09:02:17.351Z",
"tags": [
"台南",
"週末"
],
"status": "active",
"expiredAt": "",
"expiredReason": "",
"expiredCheckedAt": ""
}
];
匯入也支援 .js 與 .json,彈出視窗還能直接貼上檔案內容。選「合併」只會加入尚未存在的貼文;選「完全覆寫」前會再確認一次,按
Esc
一律視為取消。
threads-featured-data-*.js
沒有伺服器、沒有帳號,也不收集使用紀錄。你存下的貼文只寫進本機,不會被傳到任何地方。下表是擴充功能要求的每一項權限與它的用途。
| 類別 | 項目 | 用途 |
|---|---|---|
| API 權限 | storage |
讀寫本機的 chrome.storage.local,所有貼文都存在這裡。 |
unlimitedStorage |
解除 chrome.storage.local 的 10MB 配額,收藏數千篇也不會寫入失敗。 |
|
tabs |
更新貼文資料時,在背景開一個工作分頁逐篇載入,結束後關閉。 | |
scripting |
在那個工作分頁注入擷取腳本,讀回發文時間、內文與標籤。 | |
| 網站存取 | threads.com |
含 www。在貼文頁偵測內嵌對話框並擷取內容。 |
threads.net |
含 www。同樣會擷取內容,即時預覽的官方內嵌框架也從這裡載入。 | |
| 內容安全政策 | script-src 'self' |
只執行擴充功能自帶的腳本,不載入任何遠端程式碼。 |
frame-src |
預覽用的框架只允許 Threads 官方網域。 |
以下是幾個關鍵做法的精簡節錄。完整的流程圖、資料結構與注意事項都在 README,AI 工具可以直接讀 llms.txt。
對話框裡可能同時有純連結和完整內嵌碼。每個唯讀欄位依內容加權,分數最高的就是帶
data-text-post-permalink 的 blockquote。
節錄自 content.js 的
extractEmbedCodeFromDialog
let score = value.length;
if (/data-text-post-permalink=/i.test(value)) score += 1000;
if (/<blockquote/i.test(value)) score += 500;
if (/threads\.com/i.test(value)) score += 100;
只保留沒有被其他候選容器包住的最外層容器,再用 innerText 輸出。段落與
<br> 換行都留著,子節點也不會重複擷取。
節錄自 content.js 的
extractContentFromDOM
const topContainers = beforeReply.filter(el =>
!beforeReply.some(other => other !== el && other.contains(el))
);
每一輪先檢查取消與暫停,再用同一個背景分頁載入下一篇,每篇最多等 60 秒,逾時只算失敗、不標成失效。結果每 20 篇、按下暫停或佇列結束時寫回一次,只寫這幾篇各自的紀錄並合併更新欄位;佇列期間被刪除的不會被寫回來,新存的貼文也不受影響。
簡化自 dashboard.js 的背景更新流程
for (const article of articlesNeedingUpdate) {
if (cancelUpdateRequested) break;
if (isUpdatePaused) await flushPendingUpdates();
while (isUpdatePaused && !cancelUpdateRequested) {
await new Promise(resolve => setTimeout(resolve, 150));
}
const tabId = await getOrCreateWorkerTab();
const postInfo =
await fetchPostInfoWithReusableTab(tabId, article.postLink);
// 失效就標記原因,恢復就清除標記
pendingArticles.add(article);
if (pendingArticles.size >= UPDATE_PERSIST_BATCH_SIZE) {
await flushPendingUpdates();
}
}
Threads 的內嵌頁不會回報高度,所以 content.js 也注入預覽框架,用
ResizeObserver 量 .Embed 的高度,有變化才用 postMessage
回傳。控制面板只接受官方網域的訊息。
摘自 dashboard.js
function isAllowedEmbedOrigin(origin) {
if (!origin) return false;
try {
const url = new URL(origin);
const hostname = url.hostname.toLowerCase();
const allowedDomains = ['threads.net', 'threads.com', 'instagram.com'];
return allowedDomains.some(
domain => hostname === domain || hostname.endsWith('.' + domain)
);
} catch (_) {
return false;
}
}
以「載入未封裝項目」的方式安裝,支援 Manifest V3 的 Chromium 瀏覽器都能使用。
v 是目前的版本,看看更新紀錄
重新下載或 git pull 之後,到擴充功能管理頁按它的重新載入按鈕,再重新整理 Threads 頁面。
用 Git 複製專案,或下載 ZIP 後解壓縮。
git clone https://github.com/Scorpio-meow/Threadkeep.git
在網址列貼上下面的網址;Edge 請改用 edge://extensions/。
chrome://extensions/
切換頁面右上角的「開發人員模式」開關。
點「載入未封裝項目」,選取含有 manifest.json 的專案資料夾,再把「Threadkeep」釘選到工具列。
先確認已登入 Threads,未登入時官方對話框可能產生不了內嵌碼;網址也要是 threads.com 或 threads.net。如果開發者工具出現「Extension context invalidated」,代表擴充功能剛重新載入過,重新整理 Threads 頁面就會恢復。如果 Threads 顯示「發生錯誤。這可能是技術錯誤所導致…」,或擴充功能跳出「Threads 回報錯誤」「找不到可儲存的內嵌程式碼」,都是 Threads 這次沒產生內嵌碼,稍等一下再點一次「取得內嵌程式碼」就好。
背景更新時,如果貼文被刪除、帳號轉為私密、頁面不存在或網址被轉導,就會標記為失效並記下原因,例如 post-not-found 或
redirected。之後只要貼文恢復可讀,下次更新就會自動解除。載入超過 60 秒仍拿不到結果時,只會記為這次更新失敗,不會標成失效。
Threads 對這篇的內嵌頁回了錯誤,可能是貼文已刪除、不公開,或只開放登入的人觀看,例如被列為敏感內容。若是最後一種,在同一個瀏覽器登入
threads.com 後按「重新載入」就能預覽;這類貼文的內嵌碼放到網站上時,只有已登入 Threads、且瀏覽器允許第三方 Cookie 的訪客看得到。開發者工具裡關於
Permissions-Policy 的警告來自 Meta
的回應標頭,正常的貼文也會出現,和這個錯誤無關。
擷取依賴 Threads 網頁的結構與 class 名稱,官方大幅改版時可能暫時失效。請到 GitHub Issues 回報,維護者會更新
content.js 裡的選擇器。
chrome.storage.local 的預設配額是 10MB,每篇含官方內嵌碼約 3–4 KB,大約兩、三千篇就會用完。擴充功能宣告了
unlimitedStorage 權限解除這個上限,實際容量取決於磁碟空間。仍建議定期匯出完整備份。
刪除、批次刪除與清除全部都能復原:畫面下方的提示會出現「復原」按鈕,8 秒內按下就還原;滑鼠移到提示上,或用鍵盤把焦點移到「復原」按鈕時,倒數會暫停。提示消失後就無法復原,所以清空前建議先匯出完整備份。
不會。貼文只存在瀏覽器的 chrome.storage.local,擴充功能沒有自己的伺服器,也沒有任何追蹤或統計。需要連網的只有 Threads
相關功能(官方內嵌預覽與背景更新),以及介面使用的 Google Fonts 字型。
需要能安裝擴充功能的桌面版 Chromium 瀏覽器,例如 Chrome、Edge、Brave、Opera 或 Arc。