1. はじめに
お疲れさまです。
SNSを利用していて、いきなり、センシティブな画像が送られてきて、びっくりした経験はございませんか?
自分の心理負担軽減用ではありますが、
センシティブ画像の表示をブロックして、ブロック画像を表示するか選択できるChrome拡張機能を開発しました。
TensorFlow.js x NSFWJS(nsfwjs) x Node.jsで開発してます。
本記事では、機能のイメージ、技術的なポイント、作成した拡張機能のソース等について記します。
開発したChrome拡張機能の概要
- X(旧Twitter)のDMやタイムラインを表示した時、拡張機能が画像をチェックし、画像のセンシティブ度合いを判定します。
- 拡張機能内のNSFWJSの画像判定により、判定閾値を超えた画像は「不適切な画像」としてブロック表示します。
- Xのブロック画像に「クリックで表示」ボタンを表示します。
- もし、ブロック画像を表示したい場合、「クリックで表示」ボタンをクリックする事で、個別に画像を表示できます。
なお、本拡張機能は、ユーザー(私)のWebブラウザ内で画像表示を制御するものであり、Xの画像スクレイピングや自動操作をするものではございません。
2. 解決したい課題
最近、時間ができたので、久しぶりに、X(旧Twitter)の利用を再開しました。
そんな中、とある初見の方から、なぜか、DMで若干センシティブな画像を頂くことがございました。
(具体的にどんな画像であったかは、プライバシーに関わると思うので、詳細は伏せさせて下さい)
いきなりセンシティブ画像が届きますと、びっくりしてしまいますので、何かしら対策できないかな?と考えました。
ひとまず、自分の心理負荷軽減のため、Chrome拡張機能で、Xのセンシティブ画像表示をブロックする機能を開発しました。
3. Chrome拡張機能の使い方と画像表示イメージ
本Chrome拡張機能は、以下の環境で動作を確認しております。
- OS: macOS Tahoe 26.3 (Apple M3)
- Webブラウザ: Google Chrome バージョン 145.0.7632.117(公式ビルド)(arm64)
当該環境における拡張機能の使い方と画像表示イメージを記します。
拡張機能の使い方
(1) Chrome 右上のケバブメニュー(縦の三点リーダー)から「拡張機能」→「拡張機能の管理」を開く。
(2) 「拡張機能」の「デベロッパーモード」をONにする。
(3) 「パッケージ化されていない拡張機能を読み込む。」をクリックして、本拡張機能を読み込む。
(4) Chromeから X(旧Twitter) を開く。
(5) Chrome拡張機能が、DMやタイムラインの画像をチェックし、NSFWJSでセンシティブ判定された画像の場合、ブロック表示する。
以下は、水着画像を検索して、画像がブロックされている例です。
拡張機能のブロック画像表示イメージ
XのDMやタイムラインを表示した時、NSFWスコアが閾値を超えた画像は「不適切な画像」としてブロック表示します。
もし、ブロックされた画像を表示したい場合は、ブロック画像の「クリックで表示」ボタンをクリックすると、画像を表示できます。
補足
- 一応、Xには「設定とプライバシー」->「プライバシーと安全」->「表示するコンテンツ」->「センシティブな内容を含む可能性のあるメディアを表示する」という設定があります。
4. Chrome拡張機能の技術的な情報
拡張機能の処理の流れ
拡張機能の処理の流れは以下になります。
技術スタック
拡張機能で利用している技術スタックは以下になります。
| ライブラリ | バージョン | ライセンス | 用途 |
|---|---|---|---|
| TensorFlow.js Core | 3.21.0 | Apache 2.0 | ML推論エンジン |
| TensorFlow.js WASM Backend | 3.21.0 | Apache 2.0 | WASMバックエンド(eval不要) |
| TensorFlow.js Layers | 3.21.0 | Apache 2.0 | LayersModel読み込み |
| TensorFlow.js Converter | 3.21.0 | Apache 2.0 | GraphModel読み込み |
| NSFWJS | 2.4.2 | MIT | NSFWモデル(MobileNet v2ベース) |
| Node.js | 25.6.1 | MIT | 拡張機能の実装に利用 |
技術的なポイント
- 拡張機能はPC内のローカル処理のみ、外部へのデータ送信なし
- 拡張機能はPC内のローカル処理のみで、外部サーバーやシステムへのデータ送信はしておりません。
- 本要件を実現するため、TensorFlow.js、NSFWJS(nsfwjs)を利用して、画像のセンシティブ判定をしております。
- なお、TensorFlow.jsはApache 2.0ライセンス、NSFWJS(nsfwjs)はMITライセンスです。ライセンスに則って利用しております。
- Manifest V3 × TensorFlow.jsについて
- 開発中に挙動を確認していると、Chrome拡張Manifest V3では Content Security Policyにより eval および new Function が禁止されているようでした。
- TensorFlow.js のCPUバックエンドはこれらを使用するため、WASM(WebAssembly)バックエンドを採用し、browserifyで eval を含まないバンドルを生成することで対応しています。
- Offscreen Documentの活用について
- TensorFlow.js の実行にはDOM環境が必要なため、Manifest V3 の Offscreen Document API を使用してバックグラウンドでモデルを実行しています。
- 画像のセンシティブ判定のデフォルト閾値について
- NSFWJSの画像判定の閾値は数値で指定します。
- デフォルト値は厳しめの0.3としております。
// NSFWJSの画像判定の閾値
// 0.3 厳しめ、水着画像程度でもブロック
// 0.5 水着などの画像でもブロックされる可能性あり
// 0.65 バランス型
// 0.8 緩め、明確なセンシティブ画像だけブロック
const CONFIG = { threshold: 0.3, minImageSize: 100 };
const approvedUrls = new Set();
let isEnabled = true;
const pendingRequests = new Map();
let requestCounter = 0;
console.log('[NSFW Guardian] content.js 起動');
chrome.storage.sync.get({ enabled: true, threshold: 0.3 }, (items) => {
isEnabled = items.enabled;
CONFIG.threshold = items.threshold;
console.log('[NSFW Guardian] 設定読み込み完了:', items);
});
(全文は長いので省略)
拡張機能のソース
開発したChrome拡張機能のソースは、こちらのリポジトリ に登録しております。
拡張機能の補足
- 本Chrome拡張機能はローカル処理のみです。
- 画像データは外部サーバーやシステムへ送信しません。
- 本Chrome拡張機能はユーザーのWebブラウザ内で画像表示を制御するものであり、Xの画像スクレイピングや自動操作をするものではございません。
- 非APIの自動化(Xをスクリプトで操作)をするものではございません。
- WASM(WebAssembly)のマルチスレッドを無効化しているため、画像チェック時の推論に数百ms程度かかります。
- 画像判定精度については、NSFWJSモデルの性能に依存いたします。
- 100%の精度で、センシティブ画像を判定できない可能性がございます。
5. 最後に
記事を閲覧いただき、ありがとうございます。
何かしら、Chrome拡張機能を自作される方にとって、参考になれば幸いです。
なお、今回の拡張機能は、あくまで自分用に自作したものですが、Xで類似事例を検索していると、他にも、知らない方から、いきなり過激なセンシティブ画像が送られてくる。といった事例に直面している方が、何名かいらっしゃるようでした。
ここからは私の主観ですが、X利用者さまの中には、センシティブ画像が届いた場合、不意に画像を見てしまい、強いショックを受けて、傷ついてしまう方がいらっしゃるかもしれません。
もし、類似事例で、お困りの方が多数いるようでしたら、
- 自作した拡張機能をブラッシュアップして、Chromeウェブストアで拡張機能を公開できるよう審査申請してみる。
- (※) Chromeウェブストアへ申請する場合、プライバシーポリシーの作成、データの扱いの透明性の証明など、諸々と審査があると思いますので、準備が必要と考えております。
- X社様へセンシティブ画像の表示判定を強化できないか相談してみる。
など、自分なりに、お困りの方の課題解決に取り組んでいきたいと考えています。
以上となります。






