> ## 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.

# ID変換

X（旧Twitter）のユーザー名、数値のユーザーID、プロフィールURLを相互に変換します。3つの軽量なユーティリティは、それぞれ1回につき1リクエストです。新規アカウントにはカード不要の無料100リクエストがあり、すぐに始められます。

> **注：** ユーザー名、ID、プロフィールリンクの詳細は、ブログの[Twitter ID Converter：ユーザー名、ユーザーID、プロフィールリンク](https://api.sorsa.io/blog/twitter-id-converter)を参照してください。

> **コードなしで変換：** 単発の変換には無料の[Sorsa ID Converter](https://api.sorsa.io/playground/id-converter)が使えます。ユーザー名、ID、URLを貼り付けるとすぐに結果が得られ、APIキーも不要です。

***

## ユーザーIDが重要な理由

ユーザー名はいつでも変更でき、手放した名前を別の人が取得できます。一方、数値のユーザーIDはアカウント作成時に付与され、変わりません。Xアカウントを保存・参照するシステムではIDを使ってください。

* **名前の変更でシステムが壊れません。** 何回改名してもIDは同じアカウントを指します。
* **IDの全桁を保持してください。** JSONとJavaScriptでは文字列にします。データベースで整数列を使う場合、精度を失わずに保存できる範囲か確認します。
* **異なる時点のデータを安全に結合できます。** 収集時期が異なるアカウント情報を照合するには、IDが唯一の安全なキーです。
* **IDベースのエンドポイントもあります。** `/info-batch`は`user_ids`配列を受け付けます（`usernames`も可）。リストやコミュニティは、その対象の数値IDで参照します。

## ユーザーIDの形式

XはSnowflake IDを使います。日時、マシンID、連番を1つの64ビット整数にまとめた形式で、ツイートIDには2010年から使われています。

ユーザーIDは事情が異なります。Snowflake導入後も数年間は連番の整数が付与され、2020年頃にSnowflakeへ移行しました。そのため古いアカウントは短いID（Jack Dorseyのアカウントは`12`）を持ち、2020年以降のアカウントは19桁です。古いユーザーIDから作成日時は復元できません。登録日が必要ならプロフィールの`created_at`を取得してください。

***

## エンドポイント1：ユーザー名からIDへ

```http theme={null}
GET /v3/username-to-id/{user_handle}
```

`@`なしのユーザー名を永続的な数値のユーザーIDに変換します。

```bash theme={null}
curl "https://api.sorsa.io/v3/username-to-id/elonmusk" \
  -H "ApiKey: YOUR_API_KEY"
```

```json theme={null}
{"id": "44196397"}
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"

def username_to_id(handle: str) -> str:
    resp = requests.get(
        f"https://api.sorsa.io/v3/username-to-id/{handle}",
        headers={"ApiKey": API_KEY},
    )
    resp.raise_for_status()
    return resp.json()["id"]

print(username_to_id("elonmusk"))  # "44196397"
```

```javascript theme={null}
async function usernameToId(handle) {
  const resp = await fetch(
    `https://api.sorsa.io/v3/username-to-id/${handle}`,
    { headers: { "ApiKey": "YOUR_API_KEY" } }
  );
  return (await resp.json()).id;
}
```

## エンドポイント2：IDからユーザー名へ

```http theme={null}
GET /v3/id-to-username/{user_id}
```

数値のユーザーIDから現在のユーザー名を取得します。保存済みIDを読みやすく表示したり、前回の確認以降の改名を見つけたりできます。

```bash theme={null}
curl "https://api.sorsa.io/v3/id-to-username/44196397" \
  -H "ApiKey: YOUR_API_KEY"
```

```json theme={null}
{"handle": "elonmusk"}
```

```python theme={null}
def id_to_username(user_id: str) -> str:
    resp = requests.get(
        f"https://api.sorsa.io/v3/id-to-username/{user_id}",
        headers={"ApiKey": API_KEY},
    )
    resp.raise_for_status()
    return resp.json()["handle"]
```

## エンドポイント3：プロフィールリンクからIDへ

```http theme={null}
GET /v3/link-to-id?link={profile_url}
```

完全なプロフィールURLから永続的なユーザーIDを取得します。表計算ファイル、ブックマーク、収集したページのリンクをIDに統一するときに便利です。

```bash theme={null}
curl "https://api.sorsa.io/v3/link-to-id?link=https://x.com/elonmusk" \
  -H "ApiKey: YOUR_API_KEY"
```

```json theme={null}
{"id": "44196397"}
```

```python theme={null}
def link_to_id(profile_url: str) -> str:
    resp = requests.get(
        "https://api.sorsa.io/v3/link-to-id",
        headers={"ApiKey": API_KEY},
        params={"link": profile_url},
    )
    resp.raise_for_status()
    return resp.json()["id"]
```

> **ヒント：** IDと完全なプロフィールの両方が必要なら、変換を省き、[`/info`](https://docs.sorsa.io/ja/api-reference/users-data/user-profile)に`username`を渡します。1リクエストで`id`を含む全プロフィールが返ります。他の方法は[API利用の最適化](https://docs.sorsa.io/ja/optimizing-api-usage)を参照してください。

***

## よく使うパターン

### まとめて変換する

CRMの出力、競合一覧、表計算ファイルなどにあるユーザー名を、すべてIDへ変換する例です。

```python theme={null}
import requests
import time

API_KEY = "YOUR_API_KEY"
BASE = "https://api.sorsa.io/v3"
HEADERS = {"ApiKey": API_KEY}


def batch_username_to_id(handles, pause=0.05):
    """
    Resolve a list of handles to user IDs.
    Returns: dict mapping handle -> id (or None if lookup failed).
    """
    results = {}
    for handle in handles:
        handle = handle.strip().lstrip("@")
        try:
            resp = requests.get(f"{BASE}/username-to-id/{handle}", headers=HEADERS, timeout=10)
            if resp.status_code == 200:
                results[handle] = resp.json()["id"]
            elif resp.status_code == 404:
                results[handle] = None  # Account does not exist or is suspended
            elif resp.status_code == 429:
                time.sleep(1)
                retry = requests.get(f"{BASE}/username-to-id/{handle}", headers=HEADERS, timeout=10)
                results[handle] = retry.json()["id"] if retry.status_code == 200 else None
            else:
                results[handle] = None
        except requests.RequestException:
            results[handle] = None
        time.sleep(pause)
    return results


handles = ["NASA", "SpaceX", "Tesla", "OpenAI", "stripe"]
id_map = batch_username_to_id(handles)

for handle, uid in id_map.items():
    print(f"@{handle} -> {uid or '(not found)'}")
```

逆方向も同様で、URLを`/id-to-username/{user_id}`に替え、レスポンスの`handle`を読みます。古い表示名が残っているデータベースの更新に便利です。

### 混在する入力を正規化する

ユーザー名、URL、IDが混在する入力は、すべてユーザーIDに統一します。次の処理は、入力がすでにIDならAPI呼び出しを省きます。

```python theme={null}
def normalize_to_id(value: str) -> str:
    """
    Accepts a handle, an @handle, a profile URL, or a numeric ID.
    Returns the numeric user ID.
    """
    value = value.strip().lstrip("@")

    if value.isdigit():
        return value

    if "x.com/" in value or "twitter.com/" in value:
        return link_to_id(value)

    return username_to_id(value)


# All four return the same ID
for source in ["elonmusk", "@elonmusk", "https://x.com/elonmusk", "44196397"]:
    print(normalize_to_id(source))
```

取り込みパイプラインの最初に使うと、後続の処理が常に安定した識別子を扱えます。

### ユーザー名の変更を検出する

収集時にIDとユーザー名の両方を保存していれば、定期的にIDから名前を再取得して、改名したアカウントを見つけられます。

```python theme={null}
def detect_renames(records):
    """
    records: list of {"user_id": str, "stored_handle": str}
    Returns: list of accounts that have renamed.
    """
    changes = []
    for record in records:
        try:
            current = id_to_username(record["user_id"])
        except requests.HTTPError:
            continue  # Deleted, suspended, or transient error

        if current and current.lower() != record["stored_handle"].lower():
            changes.append({
                "user_id": record["user_id"],
                "old_handle": record["stored_handle"],
                "new_handle": current,
            })
        time.sleep(0.05)
    return changes
```

さらに詳しく調べるには、[`/about`](https://docs.sorsa.io/ja/api-reference/users-data/account-about-info)の`username_change_count`と`last_username_change_at`を使います。現在の名前に加え、変更回数と最後の変更日時も分かります。

***

## 次のステップ

* [フォロワーとフォロー中ユーザー](https://docs.sorsa.io/ja/followers-and-following)：多くの取得ワークフローはID変換から始まります。
* [オーディエンスの地域分布](https://docs.sorsa.io/ja/Audience-Geography)：`/about`は`user_id`で国情報と名前の変更履歴を返します。
* [API利用の最適化](https://docs.sorsa.io/ja/optimizing-api-usage)：プロフィールも必要なら`/info`で不要な変換を省く。
* [APIリファレンス](https://docs.sorsa.io/ja/api-reference-guide)：`/username-to-id`、`/id-to-username`、`/link-to-id`を含む全仕様。
