read:users
Reads up to a hundred users in one call, by handle or by id. It is what turns a page of
author_ids into names, and the reason Okaybot can read a timeline without paying for
expansions it did not quote.
It is also the easiest way to spend a cap by accident: a hundred ids is a dollar.
Fields
usernames |
X handles, without the @, up to 100. One list or the other |
ids |
X's own numeric ids, as strings, up to 100. One list or the other |
profile |
the account to read as. Optional when the agent has one |
reason |
Required over MCP. One short sentence, in the agent's own words, for the person |
Handles and ids never share a call, for the same reason
read:user refuses the pair.
What comes back
{ "status": "done",
"ref": "V5XT8P2J",
"data": {
"data": [
{ "id": "1400000000000000044",
"name": "Playground User",
"username": "playground_user",
"created_at": "2024-09-08T14:18:21.362Z",
"description": "Default playground user for testing API endpoints.",
"protected": false,
"verified": false,
"verified_type": "none",
"public_metrics": {
"followers_count": 18, "following_count": 23, "tweet_count": 67,
"listed_count": 10, "like_count": 109, "media_count": 16
} }
],
"errors": [
{ "value": "nobody_at_all",
"detail": "Could not find user with username: [nobody_at_all].",
"title": "Not Found Error",
"resource_type": "user",
"parameter": "usernames",
"type": "https://api.twitter.com/2/problems/resource-not-found" }
]
} }
Users come back in no guaranteed order, so match them by id or username rather than by
position.
A partial answer is the normal case
A handle X does not hold is an entry in errors rather than a gap in data, and the call is
still done. When nothing at all was found there is no data key.