Last updated
Twitter ID to Username — Examples
Twitter user IDs are permanent numeric identifiers, while usernames can change. This page explains how to look up the username for a user ID, why storing IDs is better than storing usernames, and how to handle the ID-username relationship in your applications.
Why User IDs Are More Reliable Than Usernames
- User IDs never change — they are assigned at account creation and are permanent
- Usernames can be changed by the user at any time
- A changed username may be claimed by a completely different account
- Storing user IDs ensures your data always points to the correct account
- Always store user IDs as the primary identifier in your database
Looking Up Username from User ID (Twitter API v2)
# Python — look up username from user ID
import requests
def get_username_from_id(user_id, bearer_token):
"""Look up the current username for a Twitter user ID."""
headers = {"Authorization": f"Bearer {bearer_token}"}
url = f"https://api.twitter.com/2/users/{user_id}"
params = {"user.fields": "name,username,created_at,description"}
response = requests.get(url, headers=headers, params=params)
data = response.json()
if "data" in data:
return data["data"]
return None
# Example usage
user_id = "44196397"
bearer_token = "YOUR_BEARER_TOKEN"
user = get_username_from_id(user_id, bearer_token)
if user:
print(f"Username: @{user['username']}")
print(f"Display name: {user['name']}")
print(f"Created at: {user['created_at']}")
Batch Lookup: Multiple User IDs to Usernames
# Python — batch lookup up to 100 user IDs at once
import requests
def batch_get_usernames(user_ids, bearer_token):
"""
Look up usernames for up to 100 user IDs in a single API call.
Twitter API v2 supports batching for efficiency.
"""
headers = {"Authorization": f"Bearer {bearer_token}"}
url = "https://api.twitter.com/2/users"
params = {
"ids": ",".join(str(uid) for uid in user_ids[:100]),
"user.fields": "username,name,created_at"
}
response = requests.get(url, headers=headers, params=params)
data = response.json()
result = {}
for user in data.get("data", []):
result[user["id"]] = {
"username": user["username"],
"name": user["name"],
"created_at": user.get("created_at")
}
return result
# Example
user_ids = ["44196397", "783214", "17919972"]
users = batch_get_usernames(user_ids, "YOUR_BEARER_TOKEN")
for uid, info in users.items():
print(f"ID {uid}: @{info['username']} ({info['name']})")
Reverse Lookup: Username to User ID
# Python — look up user ID from username
import requests
def get_id_from_username(username, bearer_token):
"""Look up the user ID for a Twitter username."""
headers = {"Authorization": f"Bearer {bearer_token}"}
url = f"https://api.twitter.com/2/users/by/username/{username}"
params = {"user.fields": "id,name,username,created_at"}
response = requests.get(url, headers=headers, params=params)
data = response.json()
if "data" in data:
return data["data"]
return None
# Example
user = get_id_from_username("twitter", "YOUR_BEARER_TOKEN")
if user:
print(f"User ID: {user['id']}")
print(f"Username: @{user['username']}")
print(f"Created at: {user['created_at']}")
Decoding Account Creation Date from User ID
Twitter user IDs use the same Snowflake format as tweet IDs. You can decode the creation timestamp from any Snowflake-era user ID:
// JavaScript — decode account creation date from user ID
function getAccountCreationDate(userIdStr) {
const id = BigInt(userIdStr);
const twitterEpoch = 1288834974657n;
// Check if this is a Snowflake ID (post-Nov 2010)
if (id < 27000000000n) {
return "Pre-Snowflake account — creation date not encoded in ID";
}
const timestampMs = (id >> 22n) + twitterEpoch;
return new Date(Number(timestampMs)).toISOString();
}
// Examples
console.log(getAccountCreationDate("783214")); // Pre-Snowflake
console.log(getAccountCreationDate("1234567890123456789")); // Snowflake
Handling Username Changes in Your Application
# Python — database pattern for tracking users by ID
import sqlite3
from datetime import datetime, timezone
def setup_db(conn):
conn.execute("""
CREATE TABLE IF NOT EXISTS twitter_users (
user_id TEXT PRIMARY KEY,
username TEXT NOT NULL,
display_name TEXT,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
def upsert_user(conn, user_id, username, display_name):
"""Store or update a user — always keyed by user_id, not username."""
conn.execute("""
INSERT INTO twitter_users (user_id, username, display_name, last_updated)
VALUES (?, ?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET
username = excluded.username,
display_name = excluded.display_name,
last_updated = excluded.last_updated
""", (user_id, username, display_name, datetime.now(timezone.utc)))
conn.commit()
def get_user_by_id(conn, user_id):
cursor = conn.execute(
"SELECT * FROM twitter_users WHERE user_id = ?", (user_id,)
)
return cursor.fetchone()
# Usage
conn = sqlite3.connect(":memory:")
setup_db(conn)
upsert_user(conn, "44196397", "elonmusk", "Elon Musk")
print(get_user_by_id(conn, "44196397"))
Handling 64-bit IDs in JavaScript
// Twitter user IDs can exceed JavaScript's safe integer limit
// Always use id_str from the API response, not id
// WRONG — may lose precision
const userId = response.data.id; // numeric, may be imprecise
// CORRECT — use the string version
const userId = response.data.id; // Twitter API v2 returns strings by default
// For v1.1 API, use id_str
const userId = response.user.id_str; // always a string
// Convert to BigInt for arithmetic
const userIdBig = BigInt(userId);
console.log(userIdBig.toString());
Rate Limiting Considerations
- User lookup by ID: 300 requests per 15 minutes (app auth)
- Batch lookup (up to 100 IDs per request): use this to minimize API calls
- Cache usernames locally and refresh periodically rather than looking up on every request
- Store the
last_updatedtimestamp to know when to refresh cached usernames
The key takeaway: always store Twitter user IDs as your primary identifier. Usernames are display names that can change, but user IDs are permanent. Building your application around user IDs ensures data integrity even when users change their handles.