5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Yahooリアルタイム検索のAPIが本当に有能だからみんな使ったほうがいい話

5
Posted at

Yahooリアルタイム検索のAPIが本当に有能だからみんな使ったほうがいい話

X(旧Twitter)の画像を検索したいとき、公式APIを使おうとすると月100ドル以上かかる。でも実はYahooリアルタイム検索のバックエンドAPIを使えば、認証不要・無料で大量のツイートと画像を取得できる。しかも思ったより高機能だったので紹介する。


TL;DR

GET https://search.yahoo.co.jp/realtime/api/v1/pagination?p=キーワード&md=h&results=40&mtype=image

これだけで認証なしにX(Twitter)の画像付きツイートが40件取れる。


基本的な使い方

const res = await fetch(
  `https://search.yahoo.co.jp/realtime/api/v1/pagination?${new URLSearchParams({
    p: "アニメ",
    md: "h",       // 人気順(省略すると新着順)
    results: "40", // 最大40件
    mtype: "image", // 画像付きのみ
  })}`,
  {
    headers: {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      "Accept": "application/json, text/plain, */*",
      "Referer": "https://search.yahoo.co.jp/realtime/search",
    },
  }
);

const data = await res.json();
const entries = data.timeline.entry;
// entries[0].media[0].item.mediaUrl で画像URLが取れる

User-Agentを偽装しないとブロックされるので注意。それ以外は特に制約なし。


何がすごいのか

1. レート制限がない(検証済み)

500連続リクエスト・1000並列リクエストを試したが、エラーは一切なかった。レスポンスヘッダーにも X-RateLimit-* 等は存在しない。

2. 並列取得で爆速

start パラメータでオフセット指定ができるため、複数ページを同時にリクエストできる。

// 4ページを並列取得(逐次比4.1倍速を確認)
const pages = await Promise.all(
  [1, 41, 81, 121].map(start =>
    fetch(`...&start=${start}`).then(r => r.json()).then(d => d.timeline.entry)
  )
);
const entries = pages.flat(); // 160件、重複なし

3. 最大10000件を並列取得 → さらにその先も取れる

start の上限は10000件だが、その後は oldestTweetId カーソルに切り替えることで無制限に続きを取得できる。600ページ(18000件超)以降も継続取得できることを確認済み。

// フェーズ1: start で並列取得(最大10000件)
const starts = Array.from({ length: 250 }, (_, i) => i * 40 + 1);
const pages = await Promise.all(starts.map(start => fetchPage({ start })));
const entries = pages.flat();

// フェーズ2: カーソルで続きを逐次取得(上限なし)
let cursor = entries.at(-1)?.id;
while (cursor) {
  const page = await fetchPage({ oldestTweetId: cursor });
  if (!page.length) break;
  entries.push(...page);
  cursor = page.at(-1)?.id;
}

4. 期間指定ができる

since / until にUnixタイムスタンプを渡すと期間絞り込みができる(日付文字列は無効)。

const since = Math.floor(new Date("2026-01-01").getTime() / 1000);
const until = Math.floor(new Date("2026-03-01").getTime() / 1000);
// ?since=1735689600&until=1740787200

5. クエリ演算子が使える

構文 説明
(A B) / A OR B OR検索
A -B NOT検索
ID:username 特定ユーザーの投稿
@username 特定ユーザー宛て
#hashtag ハッシュタグ
URL:domain URL含む投稿

例:#イラスト -AI で非AI絵師のイラストのみ取得、ID:nhk_news でNHKの投稿のみ取得、など。

6. レスポンスが情報豊富

各ツイートに以下が含まれる:

  • 画像/動画URL(media[].item.mediaUrl
  • いいね数・RT数・リプライ数・QT数
  • ユーザー情報(ID・表示名・プロフィール画像)
  • 認証バッジ(badge.type: blue=個人認証、business=企業認証)
  • 引用ツイートの内容(quotedTweet
  • センシティブフラグ(possiblySensitive
  • 動画の長さ(media[].item.duration ミリ秒)

主なパラメータ一覧

パラメータ 説明
p 文字列 検索クエリ
md h / 省略 h=人気順、省略=新着順
results 数値 取得件数(最大40)
mtype image / video 画像のみ / 動画のみ
start 数値 取得開始位置(1始まり、上限10000)
oldestTweetId ツイートID カーソルページネーション
since Unixタイムスタンプ この時刻以降のみ
until Unixタイムスタンプ この時刻以前のみ

注意点・制限

  • 日本語ツイート特化:英語クエリでも日本語ツイートが返る。海外ユーザーのツイートはほぼ取得できない
  • mtype=image 推奨:付けないとメディアなしツイートが大量に混入する(40件中6件程度しかメディアなし)
  • start 上限は10000件:それ以上は oldestTweetId カーソルで取得
  • エンゲージメント絞り込み不可min_faves:100 等のTwitter演算子は無効。クライアント側でフィルタするしかない
  • GIFのみ絞り込み不可mtype=gif は無効。mediaType === "animated_gif" でクライアント側フィルタ

ユースケース

  • 画像検索アプリ:キーワードで画像付きツイートを大量収集してギャラリー表示
  • ハッシュタグまとめ#イラスト + mtype=image でハッシュタグ画像一覧
  • 特定ユーザーの画像一覧ID:username + mtype=image
  • バズ画像モニタリングmd=h 人気順でリアルタイムトレンド把握
  • 期間アーカイブsince/until で特定期間のツイートを収集
  • 複数クエリ並列検索Promise.all でクエリ単位の並列実行

公式APIが有料化されて以来、X関連のデータ取得手段が限られていたが、このAPIは認証不要・レート制限なし・高機能と三拍子揃っている。日本語コンテンツに限定されるが、日本語圏のユーザーには十分すぎるほど使える。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?