> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sorsa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# ツイートのエンゲージメント

Xのツイートには、コメント（返信）、引用ツイート、リツイートという3種類の公開された反応があります。合計件数はツイート上で見られますが、その背後にある具体的なユーザーや内容までは分かりません。Sorsaの専用エンドポイントでは、誰が何と返信したか、誰がどんな言葉を添えて引用したか、誰がリツイートしたかを取得できます。

このガイドでは、指標の概要から個々の返信・引用・リツイートしたユーザーまで、ツイートの反応を詳しく取得する方法を説明します。

> **注：** 追加の分析例と一連のワークフローは、ブログの[Twitter Engagement API：返信、引用、リツイートしたユーザーの取得](https://api.sorsa.io/blog/twitter-engagement-api)を参照してください。

***

## 最初のステップ：ツイートの指標を取得する

個別の反応を調べる前に、まず全体を把握します。`/tweet-info`は、すべてのエンゲージメント件数を含む完全なTweetオブジェクトを返します。

### 最小限の例

```bash theme={null}
curl -X POST https://api.sorsa.io/v3/tweet-info \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tweet_link": "https://x.com/elonmusk/status/1234567890"}'
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"

def get_tweet(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/tweet-info",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()


tweet = get_tweet("https://x.com/elonmusk/status/1234567890")

print(f"Text: {tweet['full_text'][:100]}...")
print(f"Likes:    {tweet.get('likes_count', 0):,}")
print(f"Retweets: {tweet.get('retweet_count', 0):,}")
print(f"Quotes:   {tweet.get('quote_count', 0):,}")
print(f"Replies:  {tweet.get('reply_count', 0):,}")
print(f"Views:    {tweet.get('view_count', 0):,}")
print(f"Bookmarks:{tweet.get('bookmark_count', 0):,}")
```

`tweet_link`には完全なツイートURL、または数値のツイートIDを指定できます。複数のツイートには、1リクエストで最大100リンクを受け取る`/tweet-info-bulk`を使ってください（[API利用の最適化](https://docs.sorsa.io/ja/optimizing-api-usage)）。

> **ヒント：** 新規アカウントには、カード登録不要・有効期限なしの無料リクエスト100件が含まれます。[API Playground](https://api.sorsa.io/playground)では、このページのエンドポイントをコードなしで試せます。

***

## コメント（返信）

**エンドポイント：** `POST /v3/comments`

特定のツイートへの返信を返します。1ページ最大20コメントで、それぞれ独自のエンゲージメント指標と投稿者プロフィールを持つ完全なTweetオブジェクトです。

### 最小限の例

```python theme={null}
def get_comments(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/comments",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_comments("https://x.com/elonmusk/status/1234567890")
for comment in data.get("tweets", []):
    print(f"@{comment['user']['username']}: {comment['full_text'][:80]}")
```

### パラメーター

| パラメーター        | 型      | 必須  | 説明                                              |
| :------------ | :----- | :-- | :---------------------------------------------- |
| `tweet_link`  | string | はい  | 完全なツイートURL、またはツイートID。                           |
| `order_by`    | string | いいえ | 並び順：`"Relevance"`（デフォルト）、`"Recency"`、`"Likes"`。 |
| `next_cursor` | string | いいえ | 次のコメントを取得するカーソル。                                |

`order_by`を`"Likes"`にすると、API側で反応順に並べます。最初のページに「いいね」の多いコメントが入るため、上位の返信だけが必要な場合、すべてを取得して手元で並べるより効率的です。

### すべてのコメントを順に取得する

数百の返信がある場合はページネーションが必要です。Sorsaの他のエンドポイントと同じカーソル方式のループを使います。

```python theme={null}
import time

def get_all_comments(tweet_link, max_pages=20):
    """Fetch all comments under a tweet with pagination."""
    all_comments = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/comments",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        comments = data.get("tweets", [])
        all_comments.extend(comments)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_comments


comments = get_all_comments("https://x.com/elonmusk/status/1234567890")
print(f"Collected {len(comments)} comments")
```

各コメントは、本文、エンゲージメント指標、投稿者プロフィールを持つ完全なツイートです。`likes_count`で並べて反応の多い返信を見つける、`?`で質問を抽出する、`full_text`を感情分類モデルに渡す、といった使い方があります。

```python theme={null}
# Find the most-liked comments
top_comments = sorted(comments, key=lambda c: c.get("likes_count", 0), reverse=True)

for c in top_comments[:5]:
    print(f"@{c['user']['username']} ({c['likes_count']} likes): {c['full_text'][:80]}")
```

***

## 引用ツイート

**エンドポイント：** `POST /v3/quotes`

特定のツイートを引用した投稿（コメント付きリツイート）を返します。コメントと同様に、それぞれが完全なTweetオブジェクトで、追加された本文、エンゲージメント指標、投稿者プロフィールを取得できます。

### 最小限の例

```python theme={null}
def get_quotes(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/quotes",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_quotes("https://x.com/elonmusk/status/1234567890")
for quote in data.get("tweets", []):
    print(f"@{quote['user']['username']} quoted: {quote['full_text'][:80]}")
```

### パラメーター

| パラメーター        | 型      | 必須  | 説明                    |
| :------------ | :----- | :-- | :-------------------- |
| `tweet_link`  | string | はい  | 引用元ツイートの完全なURL、またはID。 |
| `next_cursor` | string | いいえ | ページネーションカーソル。         |

### すべての引用を順に取得する

```python theme={null}
def get_all_quotes(tweet_link, max_pages=20):
    """Fetch all quote tweets of a specific tweet."""
    all_quotes = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/quotes",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        quotes = data.get("tweets", [])
        all_quotes.extend(quotes)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_quotes
```

引用には投稿者のプロフィールと追加された本文があるため、引用したユーザーをリーチの規模で並べられます。

```python theme={null}
quotes = get_all_quotes("https://x.com/brand/status/1234567890")

# Find quotes that reached the largest audiences
quotes.sort(key=lambda q: q["user"].get("followers_count", 0), reverse=True)

for q in quotes[:5]:
    u = q["user"]
    print(f"@{u['username']} ({u['followers_count']:,} followers)")
    print(f"  \"{q['full_text'][:80]}...\"\n")
```

***

## リツイートしたユーザー

**エンドポイント：** `POST /v3/retweeters`

特定のツイートをリツイートした**ユーザー**を新しい順に返します。`/comments`や`/quotes`とは異なり、`TweetsResponse`ではなく`UsersResponse`（プロフィールの配列）です。ツイートのオブジェクトではなく、リツイートした人のプロフィールを取得します。

### 最小限の例

```python theme={null}
def get_retweeters(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/retweeters",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_retweeters("https://x.com/elonmusk/status/1234567890")
for user in data.get("users", []):
    print(f"@{user['username']} ({user['followers_count']} followers) retweeted")
```

### パラメーター

| パラメーター        | 型      | 必須  | 説明                |
| :------------ | :----- | :-- | :---------------- |
| `tweet_link`  | string | はい  | 完全なツイートURL、またはID。 |
| `next_cursor` | string | いいえ | ページネーションカーソル。     |

### レスポンス形式の違い

3つのエンドポイントで特に注意する点です。

| エンドポイント       | 返すデータ | レスポンスのキー | 内容                     |
| :------------ | :---- | :------- | :--------------------- |
| `/comments`   | ツイート  | `tweets` | 完全なTweetオブジェクト（本文と投稿者） |
| `/quotes`     | ツイート  | `tweets` | 完全なTweetオブジェクト（本文と投稿者） |
| `/retweeters` | ユーザー  | `users`  | ユーザープロフィールのみ           |

リツイートは元の投稿を再配信するだけで独自の本文がないため、各ユーザーのプロフィールが返されます。

### リツイートした全ユーザーを順に取得する

```python theme={null}
def get_all_retweeters(tweet_link, max_pages=20):
    """Fetch all users who retweeted a tweet."""
    all_users = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/retweeters",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        users = data.get("users", [])
        all_users.extend(users)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_users
```

各ユーザーのフォロワー数を合計すると、潜在的なオーディエンス規模の指標になります。ただし実測のリーチではありません。オーディエンスには重複があり、アカウントをフォローしていても投稿を見たとは限りません。

```python theme={null}
retweeters = get_all_retweeters("https://x.com/brand/status/1234567890")

total_reach = sum(u.get("followers_count", 0) for u in retweeters)
verified_count = sum(1 for u in retweeters if u.get("verified"))

print(f"Retweeters: {len(retweeters)}")
print(f"Combined follower reach: {total_reach:,}")
print(f"Verified retweeters: {verified_count}")
```

***

## 1ツイートの反応を完全に分析する

3つのエンドポイントを組み合わせると、投稿の成果を総合的に把握できます。各種類の全ページを取得するため、多数のリクエストになります（1ページごとに割り当て量を1件消費）。完全な内訳が本当に必要なツイートに絞ってください。

```python theme={null}
def full_engagement_report(tweet_link):
    """Generate a complete engagement report for a single tweet."""

    tweet = get_tweet(tweet_link)
    print(f"Tweet by @{tweet['user']['username']}:")
    print(f"  \"{tweet['full_text'][:100]}...\"")
    print(f"  Likes: {tweet.get('likes_count', 0):,} | "
          f"Views: {tweet.get('view_count', 0):,}")
    print()

    comments = get_all_comments(tweet_link, max_pages=10)
    print(f"Comments: {len(comments)}")
    if comments:
        top_comment = max(comments, key=lambda c: c.get("likes_count", 0))
        print(f"  Most liked: @{top_comment['user']['username']} "
              f"({top_comment['likes_count']} likes)")
        print(f"  \"{top_comment['full_text'][:80]}...\"")
    print()

    quotes = get_all_quotes(tweet_link, max_pages=10)
    print(f"Quotes: {len(quotes)}")
    if quotes:
        biggest_quoter = max(quotes, key=lambda q: q["user"].get("followers_count", 0))
        print(f"  Highest reach: @{biggest_quoter['user']['username']} "
              f"({biggest_quoter['user']['followers_count']:,} followers)")
        print(f"  \"{biggest_quoter['full_text'][:80]}...\"")
    print()

    retweeters = get_all_retweeters(tweet_link, max_pages=10)
    total_reach = sum(u.get("followers_count", 0) for u in retweeters)
    print(f"Retweeters: {len(retweeters)}")
    print(f"  Combined reach: {total_reach:,} followers")
    if retweeters:
        top_rt = max(retweeters, key=lambda u: u.get("followers_count", 0))
        print(f"  Biggest amplifier: @{top_rt['username']} "
              f"({top_rt['followers_count']:,} followers)")

    return {
        "tweet": tweet,
        "comments": comments,
        "quotes": quotes,
        "retweeters": retweeters,
    }


report = full_engagement_report("https://x.com/brand/status/1234567890")
```

### 出力例

```text theme={null}
Tweet by @brand:
  "We're excited to announce our Series B funding round of $50M..."
  Likes: 2,847 | Views: 892,000

Comments: 156
  Most liked: @tech_journalist (89 likes)
  "Congrats! What's the plan for international expansion?..."

Quotes: 43
  Highest reach: @vc_partner (284,000 followers)
  "This team has been on our radar for two years. Well deserved...."

Retweeters: 312
  Combined reach: 4,218,000 followers
  Biggest amplifier: @industry_leader (892,000 followers)
```

***

## 複数ツイートの分析（バッチパターン）

キャンペーンの全投稿など、複数ツイートの反応が必要な場合は、まず`/user-tweets`または`/search-tweets`で一覧を取得し、その後に各投稿を詳しく調べます。

```python theme={null}
def compare_tweet_engagement(tweet_links):
    """Compare engagement breakdown across multiple tweets."""
    results = []

    for link in tweet_links:
        tweet = get_tweet(link)
        comments = get_all_comments(link, max_pages=3)
        quotes = get_all_quotes(link, max_pages=3)
        retweeters = get_all_retweeters(link, max_pages=3)

        rt_reach = sum(u.get("followers_count", 0) for u in retweeters)

        results.append({
            "text": tweet["full_text"][:60],
            "likes": tweet.get("likes_count", 0),
            "comments": len(comments),
            "quotes": len(quotes),
            "retweets": len(retweeters),
            "retweet_reach": rt_reach,
        })
        time.sleep(0.5)

    print(f"{'Tweet':<62} {'Likes':>6} {'Cmts':>5} {'Qts':>4} {'RTs':>4} {'RT Reach':>10}")
    print("-" * 100)
    for r in results:
        print(f"{r['text']:<62} {r['likes']:>6} {r['comments']:>5} "
              f"{r['quotes']:>4} {r['retweets']:>4} {r['retweet_reach']:>10,}")

    return results
```

> **ヒント：** 個別のコメント、引用、リツイートしたユーザーではなく、合計指標だけが必要なら、`/tweet-info-bulk`で最大100ツイートを1リクエストで取得できます。他のバッチパターンは[API利用の最適化](https://docs.sorsa.io/ja/optimizing-api-usage)を参照してください。

***

## エンゲージメントデータをCSVに出力する

```python theme={null}
import csv

def export_comments_to_csv(comments, output_file="comments.csv"):
    fields = [
        "comment_id", "created_at", "full_text", "likes", "retweets",
        "author_username", "author_followers", "author_verified",
    ]
    with open(output_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for c in comments:
            u = c.get("user", {})
            writer.writerow({
                "comment_id": c["id"],
                "created_at": c["created_at"],
                "full_text": c["full_text"],
                "likes": c.get("likes_count", 0),
                "retweets": c.get("retweet_count", 0),
                "author_username": u.get("username", ""),
                "author_followers": u.get("followers_count", 0),
                "author_verified": u.get("verified", False),
            })
    print(f"Exported {len(comments)} comments to {output_file}")
```

引用もTweetオブジェクトなので同じ方法を使えます。リツイートした人は、ツイートではなくユーザーのフィールドを出力してください。

***

## 確認用エンドポイント：特定のユーザーが反応したか

キャンペーンやプレゼント企画などで、特定ユーザーのコメント、引用、リツイートを確認するには、専用の確認エンドポイントが使えます。`/check-retweet`はページネーションが必要になる場合があり、`/check-quoted`は真偽値ではなく状態を返します。

* `/check-comment`：指定ユーザーが返信したか
* `/check-quoted`：引用したか
* `/check-retweet`：リツイートしたか

詳細は[マーケティングキャンペーンの確認](https://docs.sorsa.io/ja/Marketing-Campaign-Verification)で説明しています。

***

## 次のステップ

* [ツイート検索](https://docs.sorsa.io/ja/search-tweets)：キーワードで投稿を見つけ、その反応を分析する。
* [メンションの追跡](https://docs.sorsa.io/ja/search-mentions)：ブランドへの言及を監視し、特に話題になった投稿の反応を分析する。
* [競合分析](https://docs.sorsa.io/ja/Competitor-Analysis)：競合のコンテンツ間で反応のパターンを比較する。
* [過去のデータ](https://docs.sorsa.io/ja/historical-data)：古いツイートを取得して反応を分析する。
* [マーケティングキャンペーンの確認](https://docs.sorsa.io/ja/Marketing-Campaign-Verification)：特定ユーザーのコメントやリツイートを確認する。
* [APIリファレンス](https://docs.sorsa.io/ja/api-reference-guide)：`/comments`、`/quotes`、`/retweeters`、`/tweet-info`、`/tweet-info-bulk`の完全な仕様。
