twitter-username
Look up any X (Twitter) account by username or numeric id — no API key, no developer account, no browser, no login.
Convert a username to a user id, a user id back to a username, and pull the public profile: display name, bio, follower and following counts, tweet count, join date, avatar, banner and verification status.
from twitter_username import resolve
user = resolve("jack")
print(user.id, user.name, user.followers_count)
# 12 jack 11177316
$ twitter-username jack -f id -f screen_name -f followers_count
{
"id": "12",
"screen_name": "jack",
"followers_count": 11177316
}
Why
The official X API costs money and rate-limits hard even on paid tiers. This library pulls the same public profile data straight from X, handles the plumbing for you, and returns clean Python objects. No token to manage, no monthly bill.
Install
pip install twitter-username
Only requests and beautifulsoup4 are required. For SOCKS proxies:
pip install "twitter-username[socks]"
Requirements
Python 3.8 or newer. Pure Python — the wheel is py3-none-any, there is
nothing to compile, and no browser, JS engine or system package is involved.
Runs unchanged on Linux, macOS and Windows, and on anything else
CPython supports (BSD, Android/Termux, iOS via CPython 3.13+). On a legacy
Windows console (cp1252, cp437) the CLI switches to UTF-8 where the terminal
allows it and otherwise emits \uXXXX-escaped JSON, so emoji and CJK display
names never crash it and the output stays valid, lossless JSON.
Usage
One-off lookups
from twitter_username import resolve, resolve_raw
resolve("jack") # by username
resolve("@jack") # leading @ is fine
resolve("https://x.com/jack") # so is a profile URL
resolve(user_id=12) # by numeric id
resolve_raw("jack") # the untouched JSON response
Many lookups — reuse a Client
Each resolve() call sets itself up from scratch. A Client keeps that setup
warm, so every lookup after the first costs a single request.
from twitter_username import Client
with Client() as client:
for handle in ["jack", "elonmusk", "python"]:
user = client.resolve(handle)
print(f"{user.screen_name:12} {user.followers_count:>12,}")
The User object
Populated fields only; anything X did not return stays None. The complete
untouched payload is always on .raw, so nothing is lost.
id screen_name name created_at |
identity |
description location url |
profile |
followers_count following_count tweet_count media_count favourites_count listed_count |
counts |
verified is_blue_verified protected possibly_sensitive |
flags |
profile_image_url profile_banner_url |
media |
raw |
the original response object |
Plus created_at_datetime, profile_url, profile_image_url_original and
to_dict(include_raw=False).
Errors
from twitter_username import resolve, UserNotFound, UserUnavailable, APIError
try:
user = resolve("some_handle")
except UserNotFound:
... # no such account (also covers suspended/deactivated)
except UserUnavailable as exc:
print(exc.reason)
except APIError as exc:
print(exc.status_code, exc.body)
All of them subclass TwitterUsernameError.
Transport failures (proxy refused, DNS, TLS, timeout) are not wrapped —
they surface as the usual requests.RequestException subclasses, so existing
requests error handling and retry policies keep working. The CLI catches them
and prints one line instead of a traceback.
Proxies
proxies accepts a single URL applied to both schemes, or a requests-style
mapping.
from twitter_username import Client, resolve
resolve("jack", proxies="http://user:pass@127.0.0.1:8080")
resolve("jack", proxies="socks5://127.0.0.1:1080") # needs [socks] extra
with Client(proxies={"http": "http://a:8080", "https": "http://b:8080"}) as c:
c.resolve("jack")
The proxy is set on the session, so it covers every request the library makes.
Custom headers
Headers merge in layers, each one overriding the last: library defaults →
session → client → individual call. Passing None as a value removes a
header the library would otherwise send.
from twitter_username import Client
with Client(
headers={"Accept-Language": "de-DE,de;q=0.9"},
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...",
) as client:
client.resolve("jack")
client.resolve("python", headers={"Referer": "https://x.com/explore"})
Bringing your own session
Pass a configured requests.Session to keep control of retries, connection
pooling, adapters and cookies. The client will not close a session it did not
create.
import requests
from requests.adapters import HTTPAdapter, Retry
from twitter_username import Client
session = requests.Session()
session.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=1)))
with Client(session=session) as client:
client.resolve("jack")
Other Client options: timeout, page_url, features, verify, cert,
trust_env, bearer, guest_token.
Command line
twitter-username jack # parsed JSON
twitter-username jack elonmusk python # batch, JSON array
twitter-username --user-id 12 # id to username
twitter-username jack --raw # full response
twitter-username jack -f id -f followers_count
twitter-username jack --compact # one JSON object per line
twitter-username jack -x socks5://127.0.0.1:1080
twitter-username jack -H 'Accept-Language: de-DE' -H 'Referer:'
Exit codes: 0 ok, 1 error, 2 usage, 3 not found, 4 unavailable.
Pipe it into jq like any other tool:
twitter-username jack elonmusk --compact | jq -r '[.screen_name, .followers_count] | @tsv'
Development
pip install -e ".[dev]"
pytest # offline tests
pytest -m network # live tests over the network
Stability
This library depends on public data whose shape X can change without notice.
Pin a version, handle BootstrapError as a signal that something upstream
moved, and open an issue if lookups start failing.
Use it for public profile data only, and respect X's terms and the law where you are. Rate-limit yourself; do not hammer it.
Keywords
twitter api · x api · twitter without api key · free twitter api · twitter scraper · x scraper · twitter username to id · twitter id to username · twitter user lookup · get twitter user id · twitter profile scraper · twitter follower count · twitter user info · x user lookup · python twitter library · twitter osint · x osint · snscrape alternative · tweepy alternative · no api key · twitter data · social media scraper · twitter account checker · username checker
License
MIT — see the LICENSE file included in the distribution.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file twitter_username-0.1.0.tar.gz.
File metadata
- Download URL: twitter_username-0.1.0.tar.gz
- Upload date:
- Size: 34.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2d9e3d1eb2ccf7e13d40314fc1e1d55ce745e4947c65eda9fd40c33ca9d191c
|
|
| MD5 |
01105a2ffd121ff2f511a17cbc36cbd0
|
|
| BLAKE2b-256 |
933a541ed010ea943a0e853cb8fb090c143b07dcd06e60f4d0a29014968abecb
|
File details
Details for the file twitter_username-0.1.0-py3-none-any.whl.
File metadata
- Download URL: twitter_username-0.1.0-py3-none-any.whl
- Upload date:
- Size: 26.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d943ddfd31ce75bc4c7b980d331048ed937b858e1d6eb87d0c2b3c854dde231f
|
|
| MD5 |
9aa76dd4ad37047222bf7ec9fb0f8b69
|
|
| BLAKE2b-256 |
a911d03dbf8499a6d1c9d472d63f0bb8076dd61f51dfe811c3cc1a10727972de
|