# Resolving a social handle to a stable id

2026-08-17

> Turn @handles into user ids and channel ids as JSON. Public resolution, not OAuth login.

- Index: https://fetcher.sh/blog.md
- This page (HTML): https://fetcher.sh/blog/resolving-a-social-handle-to-a-stable-id

![A code editor with a dark theme filling the screen](https://images.unsplash.com/photo-1555066931-4365d14bab8c?auto=format&fit=crop&w=1600&q=80)

Photo by Ilya Pavlov on [Unsplash](https://unsplash.com/?utm_source=fetcher_sh&utm_medium=referral).

Most list and timeline endpoints want a stable id. Humans show up with `@OpenAI` or `nasa`. Resolution is the lookup in between: handle in, user id or channel id out, as JSON. X, Instagram, TikTok, YouTube, Reddit.

It is not “Sign in with Twitter,” not OAuth identity, and not a session. Nobody logs in. Public resolution only. It is also not a people-search database for private records. [OSINT](/blog/osint-handle-thread-open-web) workflows start here, then reconstruct a thread, then optionally a SERP. Creator lookup and follower graphs assume you already did this step.

Handles change; ids usually do not. Store the id on day one. That sentence is the whole product.

## Handle in, id out

Twitter/X: handle and handle/about. Instagram: handle and userid-from-handle. TikTok: user/handle. YouTube: channel/handle and channel/path. Reddit: user/username. Search-users endpoints exist where the catalog has them. Downstream follower lists and timelines want the id.

`curl -H 'Authorization: Bearer bby_live_…' 'https://twitter.fetcher.sh/api/handle/OpenAI'`

YouTube can take a handle or a `/c/` path depending on the path you call — use the one the docs name. Do not send an IG shortcode to a Twitter handle path. Do not send a display name with spaces and hope.

If resolve 404s, the account may be gone, renamed, or private. Private is not a puzzle. Stop.

## Not authentication

This is not SSO and not “Sign in with X.” Nobody authenticates. Public handle resolution. Access notes for each network still apply; this note is only the resolve.

People still paste a handle into a followers URL and get a 400. That is this page’s entire support burden. Resolve, store, then list.

## A case: a spreadsheet of names that will rot

An OSINT-adjacent researcher (public accounts only) gets a CSV of handles from a colleague. In six months half of them will have changed.

They resolve every handle on day one, store ids, and only then pull threads or graphs. When a handle 404s later, they still have the id for the paths that accept it. [OSINT](/blog/osint-handle-thread-open-web) workflows start here, then reconstruct a thread, then optionally a SERP.

Creator lookup and follower graphs assume you already did this step. Skipping it is how a roster check becomes archaeology.

## A case: a YouTube `/c/` path in an email

A producer is handed `youtube.com/c/something`, not `@handle`. They use the channel/path resolve, not the handle resolve, and they store the channel id. Next week’s Shorts list works. Last year’s script that assumed `@` would have failed closed — better than fetching the wrong channel.

Same key as every other host. No Google login. No OAuth. Public lookup.

Search-users endpoints, where they exist, are for “I have a display name and a guess.” Exact handle resolve is for “I have `@OpenAI`.” Do not use search-users as a people-search engine for a legal name and a city. That is not what it is, and it is not what we sell.

When a handle 404s, write down which host you called. Teams waste a day resolving an IG handle on twitter.fetcher.sh. The error is JSON either way; the lesson is in the hostname.

Store ids in the sheet next to the handle, the date you resolved, and the host. Next quarter you re-resolve only to detect renames. You do not re-litigate every downstream path.

A weekly job can re-resolve the roster in one pass: handle in, id out, compare to last week’s id. Mismatches are renames. 404s are gone or private. That job should not pull follower graphs “while we are here.” Resolve is cheap compared to walking edges, and mixing the two is how a lookup becomes a crawl. Keep the cron boring.

If two networks share a display name and not a handle, resolve both and store both ids. Do not invent a join key. Humans still decide whether it is the same creator. The JSON only tells you that both public accounts exist.

## Public lookup, not a login

This is not SSO and not “Sign in with X.” Nobody authenticates. Public handle resolution. Docs on each host; 402 or a prepaid key from [/topup](/topup). OSINT, creator lookup, and follower graphs all assume this step already happened. If it has not, start here. A display name with spaces is not a handle; use search-users only as a guess, then resolve the real handle you found. Never treat a search-users hit as identity. Store the id only after an exact resolve you trust. That extra GET is cheaper than a wrong timeline. Reddit usernames, TikTok usernames, and X handles can look identical in a spreadsheet and still be three people. Always include the host next to the id. A bare number with no host is how next quarter’s intern fetches the wrong network. Path names differ (`handle`, `user/handle`, `channel/handle`); copy from the host docs, not from memory.
