
ユーザー名によるReddit OSINT。インデックスされた投稿、コメント、削除済みおよびライブコンテンツ、アクティビティパターン、露出した識別子、および総合的な露出スコアを発見します。
ユーザー名によるReddit OSINT。ユーザー名を渡すと、公開Redditアーカイブがそのアカウントについてインデックスしたすべての情報を返します:投稿、コメント、削除されたものと現在も残っているもの、活動パターン、漏洩した識別子、そして露出スコア。
依存関係なし、APIキーなし、ログイン不要。必要なのは python3 だけです。

python3 reddit_osint.py someuser
同じ分析は、LLMクライアント向けのMCPツールとしても利用できます。詳細はMCPサーバーを参照してください。
pip install -r requirements.txt && python mcp_server.py
Reddit は削除するが、サードパーティのデータアーカイブは削除以前に存在したコピー(少なくとも [removed] / [deleted] マーカー)を保持している。このツールはそれらのアーカイブに問い合わせ、アカウントの活動プロファイルを再構築する。
これが h3kz-reddint Web ツールの背後にある前提であり、このスクリプトのリファレンスでもある。このツールはそのパイプライン(2 つのソース、マージ、PII 正規表現、グラフ、スコア)を、テストとオプションのプロキシサポートを備えたスタンドアロン CLI として再実装している。
| ソース | 内容 | 役割 |
|---|---|---|
Arctic Shift (arctic-shift.photon-reddit.com) | 無料の Reddit アーカイブ。Pushshift のコミュニティ運営による後継。2022 年から現在までをカバーし、元のスクレイプ(selftext、removed_by_category、media_metadata、flair)を保持している。API キー不要、IP ごとのレート制限あり。 | 主要ソース。 有用なデータの 100% を提供する。 |
PullPush (api.pullpush.io) | 同じ Reddit データの別のインデックス(過去の Pushshift ダンプ)。 | フォールバック。並行してクエリされ、id でマージされる。subreddit API は 404 を返すため、投稿/コメントのみを提供する。 |
reddit.com | — | クエリされない。 レポート内のパーマリンク URL を構築するためにのみ使用される。公式 Reddit API は使用されない(ログインなし)。これが停止されたアカウントでも機能する理由である。 |
実際のサンプルアカウントで測定: Arctic Shift は 39 件の投稿 / 139 件のコメントを返し、PullPush は ID が重複する 38 件の投稿を返した。Arctic Shift が優位であり、--source arctic はより高速で十分である。
pip install は不要。標準ライブラリのみ。pip install pysocks(オプション、socks5:// の場合のみ必要)pip install -r requirements.txt(FastMCP)。CLI には不要。python3 reddit_osint.py someuser
stdout にレポートを JSON として出力し(サマリーのみ、項目ごとのダンプは含まない)、
stderr にログを出力します。
python3 reddit_osint.py someuser --json report.json
python3 reddit_osint.py someuser --json report.json --quiet > /dev/null
report.json には すべての 投稿とコメント(テキスト、subreddit、スコア、日付、ステータス、パーマリンク)を含む all_items キーが含まれます。画面上のサマリーでは、200 KB をダンプしないようにこれを省略しています。
python3 reddit_osint.py someuser --subreddit dotnet # one subreddit only
python3 reddit_osint.py someuser --keywords "kubernetes" # posts mentioning X
python3 reddit_osint.py someuser --over18 true # NSFW only
python3 reddit_osint.py someuser --source arctic # single source (faster)
python3 reddit_osint.py someuser --max-pages 10 # cap pagination (100 items/page)
python3 reddit_osint.py someuser --delay 1.0 # slower, better with proxies
python3 reddit_osint.py someuser --rate-limit-retries 0 # fail fast when throttled
python3 reddit_osint.py someuser --proxies proxies.txt
proxies.txt、1行につき1つのプロキシ。受け入れられる形式:
http://1.2.3.4:8080
https://1.2.3.4:8443
socks5://1.2.3.4:1080
socks5://user:[email protected]:1080
1.2.3.4:8080 # no scheme -> assumed http://
# comments and blank lines are ignored
重複は削除される。ファイルに有効なプロキシが含まれていない場合、スクリプトはコード 2 で終了し、 リクエストを一切行わない。
ローテーション。 プロキシはラウンドロビン方式で順に使用される。リクエストがブロック/レート制限
コードを返した場合、そのプロキシは --cooldown 秒間クールダウン状態になり、スクリプトは次のプロキシに移る:
| フラグ | デフォルト | 動作 |
|---|---|---|
--proxies FILE | — | プロキシリスト。指定しない場合: 直接接続。 |
--cooldown SECONDS | 30 | 禁止されたプロキシが待機させられる時間。 |
--max-attempts N | (proxies+1) × 3 | 諦めるまでのリクエストごとの試行上限。 |
--no-direct-fallback | off | すべてのプロキシがクールダウン中のとき、直接接続する代わりに待機する。 |
--shuffle-proxies | off | 起動時にリストをシャッフルする(最初のリクエストから負荷を分散させる)。 |
--proxy-stats | off | レポートに proxy_stats を追加する: プロキシごとの ok / banned / errors。 |
--rate-limit-retries N | 2 | API が 429/422 を返したとき、指数バックオフ(30 秒、60 秒、最大 120 秒)でページ全体をリトライする回数。 |
禁止として扱われるコード(プロキシをローテーションさせる): 401 403 407 422 429 500 502 503 504 520 521 522 523 524、およびボディに slow down / rate limit /
too many requests / timeout を含む 400/409。Arctic Shift はレート制限に
422 "Timeout. Maybe slow down a bit" を使用するため、意図的に禁止として扱われる。
404 はローテーションしない: それは不正なリクエストであり、不正なプロキシではないため、別の場所で
リトライしても解決しない。
バックオフ。 禁止後は min(cooldown, 10 s) 待機する — これは直接接続にも適用され、そこが最も
影響が大きい。ページが試行回数を使い果たした場合、fetch_all は指数バックオフ
(--rate-limit-retries、デフォルトで 2 回 = 30 秒と 60 秒)でページをリトライする。これにより、
実行中にレート制限に引っかかったときにスクリプトがコメントを黙って失うことを防ぐ。
ローテーションを含むサンプルログ:
[proxy] http://1.2.3.4:8080 blocked (429), backing off 10s -> rotating
[proxy] http://5.6.7.8:1080 failed (Connection refused), rotating
[proxy] direct connection blocked (422), backing off 10s -> rotating
[!] arctic/comments rate limited, backing off 30s (retry 1/2)
すべてのプロキシがクールダウン中の場合、スクリプトは残りの最長クールダウンを待って再試行します
(--no-direct-fallback が渡されていない限り、直接接続を使用します)。
警告: プロキシは、あなたの IP が第三者へ到達するための egress パスです。プロキシベンダーを 信頼できない場合は、このツールでプロキシを使用しないでください。
| 変数 | 目的 |
|---|---|
REDDIT_OSINT_ARCTIC | Arctic Shift URL を上書きします(ミラー、テスト)。 |
REDDIT_OSINT_PULLPUSH | PullPush URL を上書きします。 |
id, title, selftext, body, author, subreddit, created_utc, score, permalink,
url, over_18, num_comments, link_flair_text, preview.images, media_metadata,
removed_by_category.
| ステータス | 検出 |
|---|---|
removed | テキスト = [removed] または [ Removed by Reddit ]、または removed_by_category が存在する(投稿) → モデレーターが削除した。 |
deleted | テキスト = [deleted] または author == "[deleted]" → 投稿者が削除した。 |
live | それ以外すべて。 |
これがこのツールの要点です。アーカイブはコンテンツがない場合でも削除の事実を記録しており、 それ自体が有用なメタデータです。
deleted_pct を含む live/removed/deleted の内訳。total_karma, post_karma, comment_karma, num_posts,
num_comments, earliest_post_at, last_comment_at(/api/users/search から)。Americas (UTC-8..UTC-5)Europe / Middle East / Africa (UTC+0..UTC+3)Asia / Oceania (UTC+7..UTC+11)Unknown / distributed| 種類 | パターン |
|---|---|
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(誤検出の .png/.jpg を拒否) | |
| BTC | bc1…(bech32)、1… / 3…(legacy/base58)、26–59 文字 |
| ETH | 0x + 40 hex |
| XMR | 4 + 94 文字(合計 95) |
| Telegram | t.me/<user>, telegram: @<user> |
| Phone | 区切り文字付きの 10–15 桁 |
| Domains | すべての https?://host(reddit.com, redd.it, redditmedia.com, imgur.com を除外) |
| Mentions | u/<username>(対象アカウント自体は除外) |
これらは identifiers、external_domains、mentioned_users の下に表示されます。
score_exposure_0_100: コンテンツがアカウントの背後にいる人物を特定する可能性。
メール(10)、BTC(8)、ETH/XMR(6)、Telegram/電話(4)、ドメイン/メンション(各 2)に重み付けし、
30 でスケーリングして 100 で上限を設定します。PII 露出のないプロフィールは 0 とスコアされます。
トリアージとして使用してください: 高いスコアは「pwned」を意味するのではなく、「このテキストには注意が必要」を意味します。collect() -> fetch_all() for each (source, kind)
|
+-> build_search_url() GET .../search?limit=100&sort=asc&author=U&after=<ts>
+-> PoolSession.get() PoolSession -> ProxyPool.pick() -> urllib
| 429/403 -> flag proxy, rotate, wait cooldown
+-> dedup by id Set over rows from both sources
+-> cursor = min(created_utc) + 1 and page again
|
analyze() -> status, counters, histograms, regexes, score
重要なポイント: