背景
Twitter(新 X)の過去の投稿やRT(リポスト)を整理したい時、かつて定番だった「黒歴史クリーナー」などの外部サービスはAPIの仕様変更により軒並み利用できなくなっています。
また、現在動いているサードパーティ製ツールは、アカウント連携によるセキュリティリスクや、大量削除が有料プラン限定になっているケースがほとんどです。
そこで本記事では、外部アプリ連携を一切行わず、ブラウザのデベロッパーツール(コンソール)からJavaScriptを実行して、安全かつ無料でポスト・リポストを一括削除するスクリプトを紹介します。
件数が数百件〜1,000件程度の「ちょっと過去ログをきれいにしたい」というケースに最適です。
⚠️ 実行前の超重要注意点(凍結対策)
現在のXは、機械的な大量アクセスや高速な自動操作(Bot挙動)への監視が非常に厳しくなっています。
人間離れした速度で連続削除を行うと、即座にレートリミット(Rate Limit)がかかるか、最悪の場合アカウントが凍結・ロックされます。
このリスクを回避するため、本スクリプトには以下の安全機能を組み込んでいます。
- ランダムウェイト: 1動作ごとに3秒〜7秒の間で毎回ランダムに待機します。
- 大休憩(クールダウン): 50件削除するごとに、自動で2分間処理を完全に停止します。
※実戦投入する際は、必ずご自身の判断と自己責任において実行してください。
1. 自分の「ツイート(通常ポスト)」を削除するスクリプト
自分のプロフィール画面( https://x.com )を開き、F12キー(Macは Cmd + Option + I)でデベロッパーツールを開いて「Console(コンソール)」タブに以下のコードを貼り付けて Enter を押します。
(async () => {
console.log("=== ツイ消し自動化スクリプトを開始します ===");
// 設定パラメータ
const MIN_WAIT = 3000; // 最低待機時間(3秒)
const MAX_WAIT = 7000; // 最高待機時間(7秒)
const BREAK_COUNT = 50; // 何件ごとに大休憩を入れるか
const BREAK_TIME = 120000; // 大休憩の時間(2分 = 120000ミリ秒)
let deletedCount = 0;
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const getRandomWait = () => Math.floor(Math.random() * (MAX_WAIT - MIN_WAIT + 1)) + MIN_WAIT;
while (true) {
// 三点リーダー「…」ボタン(もっと見る)を取得
const menuButtons = Array.from(document.querySelectorAll('[data-testid="caret"], [aria-label="もっと見る"]'));
if (menuButtons.length === 0) {
console.log("画面内に投稿が見つかりません。下部へスクロールします...");
window.scrollBy(0, window.innerHeight);
await sleep(3000);
continue;
}
const targetMenu = menuButtons[0];
targetMenu.scrollIntoView({ block: 'center' });
targetMenu.click();
await sleep(1500); // メニュー展開待機
// ドロップダウンから「削除」ボタンを探索
const dropdownItems = Array.from(document.querySelectorAll('[role="menuitem"]'));
const deleteMenuButton = dropdownItems.find(item => item.textContent.includes("削除"));
if (!deleteMenuButton) {
console.log("この投稿は削除できないか、自分の投稿ではありません。スキップします。");
document.body.click(); // メニューを閉じる
window.scrollBy(0, 400);
await sleep(2000);
continue;
}
deleteMenuButton.click();
await sleep(1500); // ダイアログ表示待機
// 確認ダイアログの「削除」ボタンを確定クリック
const confirmButtons = Array.from(document.querySelectorAll('[data-testid="confirmationSheetConfirm"]'));
const finalDeleteButton = confirmButtons.length > 0 ? confirmButtons[0] :
Array.from(document.querySelectorAll('button')).find(btn => btn.textContent.trim() === "削除");
if (finalDeleteButton) {
finalDeleteButton.click();
deletedCount++;
console.log(`【削除成功】 合計 ${deletedCount} 件のポストを削除しました。`);
const nextWait = getRandomWait();
console.log(`次の処理まで ${Math.round(nextWait / 1000)} 秒待機します...`);
await sleep(nextWait);
} else {
console.log("確認ボタンが見つかりませんでした。");
document.body.click();
await sleep(2000);
}
// 50件ごとの保護用大休憩
if (deletedCount > 0 && deletedCount % BREAK_COUNT === 0) {
console.warn(`⚠️ 安全のため、${BREAK_COUNT}件ごとに ${BREAK_TIME / 60000} 分間の大休憩に入ります...`);
await sleep(BREAK_TIME);
console.log("=== 削除を再開します ===");
}
}
})();
「返信(リプライ)」を消したい場合
自分で発信した通常のポストだけでなく、他人の投稿に送った「返信(リプライ)」を消したい場合も、上記(1番目)のスクリプトをそのまま使用できます。
【手順】
- プロフィール画面の「返信」タブ( https://x.com )を開きます。
- その状態でデベロッパーツールを開き、上記のスクリプトを実行します。
これにより、タイムラインに並んだ自分のリプライが上から順番に自動で削除されていきます。
2. 過去の「RT(新 リポスト)」を解除するスクリプト
自分のプロフィールにある「リポスト」タブを開いた状態で、同様にコンソールへ貼り付けて実行します。緑色に点灯しているリポストボタンだけを狙い撃ちして解除します。
(async () => {
console.log("=== リポスト(RT)解除自動化スクリプトを開始します ===");
const MIN_WAIT = 3000;
const MAX_WAIT = 7000;
const BREAK_COUNT = 50;
const BREAK_TIME = 120000;
let unretweetedCount = 0;
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const getRandomWait = () => Math.floor(Math.random() * (MAX_WAIT - MIN_WAIT + 1)) + MIN_WAIT;
while (true) {
// リポスト済み(緑色)のボタンを取得
const rtButtons = Array.from(document.querySelectorAll('[data-testid="unretweet"]'));
if (rtButtons.length === 0) {
console.log("未処理のリポストが見つかりません。スクロールします...");
window.scrollBy(0, window.innerHeight);
await sleep(3000);
continue;
}
const targetButton = rtButtons[0];
targetButton.scrollIntoView({ block: 'center' });
targetButton.click();
await sleep(1500);
// 「リポストを取り消す」を選択
const confirmMenuButton = document.querySelector('[data-testid="unretweetConfirm"]') ||
Array.from(document.querySelectorAll('[role="menuitem"], button')).find(item => item.textContent.includes("リポストを取り消す"));
if (confirmMenuButton) {
confirmMenuButton.click();
unretweetedCount++;
console.log(`【RT解除成功】 合計 ${unretweetedCount} 件のリポストを解除しました。`);
const nextWait = getRandomWait();
await sleep(nextWait);
} else {
console.log("キャンセルボタンが見つかりませんでした。");
document.body.click();
window.scrollBy(0, 400);
await sleep(2000);
}
if (unretweetedCount > 0 && unretweetedCount % BREAK_COUNT === 0) {
console.warn(`⚠️ 安全のため、${BREAK_COUNT}件ごとに ${BREAK_TIME / 60000} 分間の大休憩に入ります...`);
await sleep(BREAK_TIME);
console.log("=== 解除を再開します ===");
}
}
})();
技術的な解説とTips
1. なぜDOM構造(データ属性)を使うのか?
XのUIはReactで構築されており、クラス名(css-175oi2r など)がビルドのたびにランダムに生成・変更されます。そのためクラス名指定による querySelector は数日で使えなくなります。
本スクリプトでは、比較的変更されにくい固定の識別子である data-testid="caret"(メニューボタン)や data-testid="unretweet"(リポストボタン)をベースに要素を特定しています。
2. 途中で止まってしまった場合の対処法
無限ループで画面をスクロールさせながら要素を読み込んでいきますが、ブラウザのメモリやX側のレンダリング遅延によって、稀に画面が白いままスクロールがストップすることがあります。
その場合は一度 ページをリロード(F5) し、再度コンソールにコードを貼り付けて実行すれば、残りの件数から安全に再開できます。
3. 仕様上の限界(3,200件の壁)
この方法(ブラウザ上のDOM操作)は、Xの仕様上、タイムラインを遡れる限界である直近の約3,200件までしか消すことができません。
もし何万件もの全履歴を完全に消し去りたい場合は、X公式からダウンロードした「アーカイブデータ(ZIP形式)」を読み込める有料ツール等を使用する必要があります。数万件以下の「ちょっと昔のアカウントを軽くきれいにしたい」という場合にこのコンソール手法をご活用ください。