X-Post- und Profil-JSON, Feld für Feld: eine Referenz für Agents

X-Post- und Profil-JSON, Feld für Feld: eine Referenz für Agents
Unif Engineering team
Unif Engineering team

Aktualisiert

Jedes Feld, das die kostenlosen UnifAPI-X-Endpunkte für Posts, Profile, Seiten, Rate Limits und Fehler liefern – mit Typen und Sonderfällen.

Kurz gesagt: Die X-Endpoints auf UnifAPI, kostenlos ohne Login nutzbar und pro Besucher begrenzt, liefern drei Datensätze (post, profile und den page-Wrapper um Listen) plus eine Fehlerform und drei Rate-Limit-Header. Feldnamen sind camelCase, ids sind Strings (sie überschreiten 2^53), Datumsangaben sind ISO 8601 in UTC, Zähler sind Ganzzahlen, und alles, was X nicht meldet, fehlt, statt null zu sein. Diese Seite listet jedes Feld mit seinem Typ und den Fällen, die ein Programm behandeln muss: ein Repost, der den Originalpost plus repostedBy trägt, ein Zitat, das eine Ebene tief verschachtelt ist, ein geschützter Account, der seine Zahlen, aber keine Posts liefert, und views, die X bei den meisten Posts meldet, aber nicht bei allen.

Modelle sind gut darin, JSON zu lesen, das sie schon gesehen haben. Der Unterschied zwischen einem Agent, der eine Datenquelle korrekt nutzt, und einem, der Feldnamen rät, ist, ob die Referenz in seinem Kontext oder in seinen Trainingsdaten war. Das hier ist die Referenz. Es ist dasselbe Modell, das die Viewer-Seiten für Menschen rendern, also ist das, was Sie auf /tools/x-profile-viewer sehen, exakt das, was /tools/x/profile?handle=… liefert.

Konventionen

  • Ids sind Strings. X-Ids sind 64-Bit; JSON-Zahlen verlieren oberhalb von 2^53 an Präzision. Jede id ist ein String, auch in URLs und Cursorn.
  • Datumsangaben sind ISO 8601, UTC. createdAt und joinedAt sehen aus wie 2026-10-05T22:33:56.000Z.
  • Zähler sind Ganzzahlen. Nie formatierte Strings, nie null. Ein Zähler, den X nicht gemeldet hat, wird weggelassen, nicht auf 0 gesetzt.
  • Optional heißt abwesend. Ein als optional markiertes Feld fehlt im Objekt, wenn es keinen Wert gibt. Mit "views" in post.metrics prüfen, nicht mit === 0.
  • URLs sind kanonische x.com-URLs. post.url ist https://x.com/<handle>/status/<id>; Medien-URLs zeigen auf das CDN von X und werden nie neu gehostet.

post

Geliefert von /tools/x/post (als post) sowie als jedes Element von posts.items auf profile, media und search und von replies.items auf replies.

FeldTypBedeutung
idstringPost-ID
textstringVolltext. Lange Posts (Notes) werden vollständig geliefert; der Medien-Kurzlink am Ende wird entfernt, wenn Medien angehängt sind
createdAtstring (ISO 8601)Veröffentlichungszeit
languagestring, optionalBCP-47-Code, den X erkannt hat (en, ja, …)
conversationIdstring, optionalId des Wurzel-Posts des Threads, zu dem dieser Post gehört
inReplyToPostIdstring, optionalDer Post, auf den dieser antwortet, wenn es eine Antwort ist
possiblySensitivebooleanDas eigene Flag von X
urlstringKanonische x.com-URL
authorprofile oder nullDer Autor; null nur, wenn X ihn zurückgehalten hat
metricsobjectSiehe unten
mediaArray aus mediaLeer, wenn keine vorhanden
repostedByobject oder nullGesetzt, wenn dieser Eintrag ein Repost ist: { id, handle, name } des Accounts, der repostet hat. Der Rest des Datensatzes ist der Original-Post
quotedpost oder nullDer zitierte Post, wenn dies ein Zitat-Post ist, eine Ebene tief verschachtelt (ein Zitat in einem Zitat wird nicht aufgelöst)

metrics

FeldTypBedeutung
likesinteger
repostsintegerReposts (Retweets), ohne Zitate
repliesintegerDie Antwortzahl von X; kann über der Zahl der lesbaren öffentlichen Antworten liegen
quotesintegerZitat-Posts
bookmarksinteger
viewsinteger, optionalImpressionen. X meldet sie bei den meisten Posts; fehlt, wenn nicht

media

FeldTypBedeutung
kindphoto | video | animated_gif
urlstring, optionalBild in voller Größe oder das Vorschaubild für Video und GIF
previewUrlstring, optionalHeute identisch mit url; reserviert für eine kleinere Variante
width, heightinteger, optionalOriginalabmessungen
durationMsinteger, optionalVideolänge
videoUrlstring, optionalMP4 mit der höchsten Bitrate, die X bereitstellt, auf dem CDN von X

profile

Geliefert von /tools/x/profile, /tools/x/media und /tools/x/followers (als profile), als post.author und als jedes Element von users.items auf followers.

FeldTypBedeutung
idstringNutzer-ID
handlestringOhne das @, in der Schreibweise von X (NASA)
namestringAnzeigename
verifiedbooleanJede Art von Verifizierung (blau, Regierung, Unternehmen)
verifiedTypestring, optionalGovernment, Business, … wenn X eine benennt
protectedbooleanPosts sind nicht öffentlich. Die Endpoints liefern Zahlen, aber keine Posts
biostringKann leer sein
locationstringFreitext, kann leer sein
websitestring, optionalAufgelöste URL, nicht der t.co-Kurzlink
joinedAtstring (ISO 8601)
avatarUrlstring, optionalVariante in 400×400
bannerUrlstring, optional
followersinteger
followinginteger
postsintegerGesamtzahl der Posts
listedinteger, optionalListen, auf denen der Account steht, wenn gemeldet
pinnedPostIdstring, optional
urlstringhttps://x.com/<handle>

/tools/x/profile ergänzt engagementRate: der Durchschnitt aus Likes, Antworten, Reposts und Zitaten pro Originalpost auf der Seite, geteilt durch die Follower, als Prozentwert mit vier signifikanten Stellen. Reposts sind vom Durchschnitt ausgenommen. Für einen Account mit 90 Millionen Followern ist das eine kleine Zahl (0.0058), was korrekt ist und kein Fehler.

page

Jede Liste ist eingepackt:

{ "items": [ … ], "hasMore": true, "nextCursor": "DAAHCgABHUAq3YL__-wLAAIAAAATMj…" }
FeldTypBedeutung
itemsarraypost-Datensätze, oder profile-Datensätze auf followers, oder community-Datensätze
hasMorebooleanGenau dann true, wenn nextCursor gesetzt ist
nextCursorstring oder nullOpak. Als cursor= zurückgeben, um die nächste Seite zu bekommen

Seitengrößen: 10 Posts auf profile, 12 auf media, 20 auf replies, search und communities, 50 auf followers, 30 Trends. Cursor sind opak; manche sehen aus wie 20@, manche wie die DAAH…-Strings von X selbst. Nie parsen.

/tools/x/trends liefert { woeid, locationSlug, generatedAt, trends: [ { rank, name, postCount?, url } ] }. postCount ist nur bei den Trends vorhanden, für die X ein Volumen meldet; für die meisten Standorte sind das heute keine, also als optional behandeln. url ist die Live-Suche auf x.com.

/tools/x/communities liefert { query, communities: page }, wobei jedes Element { id, name, description, memberCount?, access?, joinPolicy?, createdAt?, url } ist.

Rate-Limit-Header

In jeder Antwort, ob Erfolg oder Fehler:

X-RateLimit-Limit: 20
X-RateLimit-Remaining: 17
X-RateLimit-Reset: 1791357984

Reset sind Unix-Sekunden, zu denen das aktuelle 10-Minuten-Fenster endet. Eine Suche kostet 2 Einheiten, alles andere 1. Ein 429 ergänzt Retry-After in Sekunden.

Fehler

Jede Nicht-2xx-Antwort ist:

{ "error": { "type": "not_found", "message": "X user not found: @nobody_here_123" } }
typeHTTPWann
validation_error400Fehlende oder fehlerhafte Eingabe (Missing handle: pass ?handle=…)
not_found404Kein solcher Account oder Post; gesperrte Accounts werden in der Meldung genannt
rate_limited429Kostenloses Limit erreicht; der Body ergänzt retryAfterSeconds und upgrade
upstream_error502Die Datenschicht von X hat mit einem Fehler geantwortet
upstream_unavailable503Timeout oder nicht erreichbar
not_configured503Das Deployment hat keine Upstream-Zugangsdaten

Nach type verzweigen; message ist für Menschen und kann sich ändern.

Markdown-Modus

Mit format=md oder dem Header Accept: text/markdown an einem beliebigen Endpoint wird derselbe Datensatz als Markdown gerendert: eine Überschrift mit dem Autor, der Text, eine Zeile Metriken, Medien-Links, die URL und eine Fußzeile mit dem nächsten Cursor. Er trägt jedes Feld von oben außer den rohen ids im Autor-Objekt und ist der günstigste Weg, ein Profil oder einen Thread in den Kontext eines Modells zu bringen.

Wo die Beispiele liegen

Die Markdown-Seite jedes Tools enthält eine aufgezeichnete echte Antwort für ihren Endpoint, gekürzt auf wenige Elemente: /tools/x-profile-viewer/index.md, /tools/x-post-viewer/index.md, /tools/x-search/index.md und so weiter. /llms.txt listet alle acht mit je einer Beispiel-URL. Die abgerechnete X / Twitter API verwendet hinter einem Workspace-Key dieselben Feldnamen, sodass Code, der gegen die kostenlosen Endpoints geschrieben wurde, ohne Änderungen umzieht.