TwitterInternalAPIDocument tracks what the web app calls behind the scenes
Twitter Internal API Document
At a glance
- What is it?
- This repository reverse engineers the internal API behind Twitter's web client and republishes it as Markdown and JSON, with the develop branch regenerated every day at 21:00 UTC. It is a research artifact rather than a supported client, and the README says plainly that the result is incomplete and favours automation over accuracy.
- Who is it for?
- Adopt this repository when you are studying how a large web client is put together, or when you maintain tooling that has to follow a moving internal API, and when you are prepared for the documentation to be wrong and the endpoints to change under you. Do not adopt it as a production dependency, and do not read the JSON files as a contract.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four branches, one of them replaced every day
The repository holds reverse engineering of the web version of Twitter, and the branch layout is the first thing to understand. There is a stable branch on master, a develop branch whose documentation is automatically updated to the latest version every day at 21:00 UTC, a logged in branch named twitter-login, and a Twitter Blue branch named twitter-blue. The logged in and Blue branches exist because the client sends different requests depending on the account, so the surface area of the API is not one API but several.
The README is blunt about the limits. It says the repository is not complete, that this follows from the limitations of static code analysis, and that the document is dedicated to automated analysis at the expense of accuracy. It repeats that what is published is incomplete documentation of Twitter's internal API and that this is the limit of static analysis and very difficult to improve the system any further.
The audience follows from that. This is a research notebook that a machine keeps current, not a specification a team builds against. The value is in seeing the shape of the client and catching changes, and the risk is that a field you rely on was never right in the first place.
The document set spans GraphQL, REST and static data
What is published is a set of files under `docs/`, in two formats. The GraphQL part has a Markdown document at `./docs/markdown/GraphQL.md` and a JSON version at `./docs/json/GraphQL.json`, plus a Change Log at `./docs/markdown/ChangeLog.md`. The v1.1 API has the same pairing, `./docs/markdown/v1.1.md` and `./docs/json/v1.1.json`.
Then there are the artefacts that are not endpoints at all. A Static Constants document and JSON describe the freeze objects the client ships, under `./docs/markdown/FreezeObject.md` and `./docs/json/FreezeObject.json`. There are JSON dumps for internationalization, the script list, the initial state and the metadata, in `./docs/json/i18n`, `./docs/json/ScriptLoadJson.json`, `./docs/json/InitialState.json` and `./docs/json/MetaData.json`. A reverse engineering note written by the developer sits at `./docs/markdown/RE.md`.
The two formats serve different needs, and that is the practical point. The JSON is what a tool consumes, and it is what the generator rewrites every day. The Markdown is what a human reads, with prose about what each operation does. If you are diffing two days of output, the JSON will tell you what changed; if you are trying to understand what an operation means, the Markdown is where the explanation lives.
The generator is a Python script with a uv managed environment
The documents are produced by a generator, and the README gives the command to run it:
uv run python generator.pyThe project file describes what that pulls in:
[project]
name = "twitter-internal-api-document"
version = "0.0.0"
description = "Reverse engineering of the web version of Twitter"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"coloredlogs>=15.0.1",
"pandas>=3.0.6",
"pygithub>=2.10.0",
"requests>=2.34.2",
"tabulate>=0.10.0",
"tqdm>=4.70.1",
]The dependency list describes the pipeline more clearly than any prose would. `requests` fetches the web client's JavaScript, `pandas` handles the extracted data, `tabulate` renders the tables, `tqdm` shows progress over a long extraction, `coloredlogs` writes readable logs, and `pygithub` publishes the results back to the repository, which is how the daily commit on the develop branch happens. The package is not distributed, since the file sets `package = false` under `[tool.uv]`, and the version is pinned at 0.0.0 because this is a tool, not a library. The dev dependency group is `ruff` alone, configured with a line length of 88.
The repository also carries `generator.py`, a `lib/` directory, `pyproject.toml` and `uv.lock` at the root, and a `.vscode/` directory.
X-Client-Transaction-Id gets its own daily job
One header gets a section of its own, because it is the piece that breaks most often. The README asks about the X-Client-Transaction-Id header and answers with a schedule: unobfuscate `ondemand.s` every day at 22:00 UTC, with a pointer to a separate repository, twitter-tid-deobf-fork, that does that work.
The reason this needs its own process is structural. The web client computes a per-request transaction identifier from obfuscated JavaScript that the site ships, and the obfuscated form changes. A static copy of the algorithm goes stale, and a stale algorithm produces requests the server refuses. So the repository treats deobfuscation as a daily job on its own schedule, one hour after the main documentation refresh at 21:00 UTC.
This is the clearest illustration of what the whole project is. The client is not a stable contract, it is a moving target that has to be re-measured, and this repository is a machine that does the measuring so a human does not have to.
What static analysis recovers, and what it cannot
The README explains the method's shape in a paragraph. You can find out information about APIs under development that cannot be called from the UI, and the document also serves as a reverse engineering assistant. The generator reads the JavaScript the web app ships, and the operations, query hashes, freeze objects and initial state come out of that code.
Two consequences follow, and they pull in opposite directions.
The first is reach. Because the analysis reads the client rather than the server, it surfaces endpoints that exist in the code but are not reachable from the user interface, which is exactly the information a person clicking through the app could never obtain. It also sees the client's own constants and metadata, so you learn how the app is configured, not only what it calls.
The second is reliability. Static analysis of minified, obfuscated JavaScript cannot tell you the semantics of a field, only its presence and shape. A documented field might be a real parameter, a leftover, or something the server ignores. The README resolves this by choosing breadth over precision, stating that the document is dedicated to automated analysis at the expense of accuracy, and by pointing at a second project, twitter-openapi, for accurate documentation.
Release tags lag far behind the daily commits
The release history looks abandoned next to the commit activity. The only listed release is v1.7, dated 2023-02-03, while the last push was on 2026-10-20 and the develop branch is rewritten daily. The version gap is explained by the design: the published artefact of this project is the branch content, not a tagged release, so there is no reason to cut a version for a commit that exists only to keep the documentation current.
That distinction is worth holding on to if you are automating against this repository. A tag such as v1.7 is a frozen copy of the documentation at a moment, while the develop branch is a moving target that will differ tomorrow. Pinning to a tag gives you a stable document that is increasingly wrong; tracking develop gives you a current document that changes without notice. Neither is an API guarantee.
The repository carries a LICENSE file that GitHub classifies as a custom licence, and the top level holds `.github/`, `.gitignore`, `.vscode/`, `docs/`, `generator.py`, `lib/`, `pyproject.toml` and `uv.lock`. The topic tags describe the repository honestly as api, documentation, graphql, scraper, twitter, undocumented and unofficial, and the README closes with a reference to another project of the same author, latest-user-agent, for the client string side of the same problem.
Where this fits, and where it does not
The honest use of this repository is research and maintenance of your own reverse engineering. If you are studying how a large web client is structured, or you have a tool that has to keep working against a moving internal API and you want a public record of what changes and when, the daily regeneration and the Change Log are genuinely useful.
The wrong use is as a dependency. Nothing here is an interface guarantee. The fields may be wrong, the operations may be renamed, the endpoints may be rate limited or blocked, and none of that is announced. The README's own framing, that the document is the limit of static analysis and dedicated to automation at the expense of accuracy, is the warning label, and it is written by the person who built the thing.
The alternative is the documented public interface, where behaviour is published and changes are announced. The cost is that it exposes only what the vendor has chosen to expose, and it is a different, narrower surface than the one the web client uses. The README points at a third path too, the twitter-openapi repository, for accurate documentation, which is the sensible middle ground: use a description of the API that aims for correctness, and treat the automated repository as the early warning system for what the client has started to do.
Editorial conclusion
Adopt this repository when you are studying how a large web client is put together, or when you maintain tooling that has to follow a moving internal API, and when you are prepared for the documentation to be wrong and the endpoints to change under you. Do not adopt it as a production dependency, and do not read the JSON files as a contract. Verify first which branch you are reading, since the develop branch is replaced daily while master holds the stable copy, check the Change Log for the operations that disappeared, and read the LICENSE file in the repository root, since GitHub classifies this licence as custom and the newest tag, v1.7, is still dated 2023-02-03.
Frequently asked questions
What is TwitterInternalAPIDocument?
It is reverse engineering of the web version of Twitter, published as Markdown and JSON files under docs/, covering the internal GraphQL API, the v1.1 API, static constants, internationalization, the script list, initial state and metadata. The README describes it as incomplete documentation produced by static code analysis.
How often is the documentation updated?
The README says the documentation in the develop branch is automatically updated to the latest version every day at 21:00 UTC. Separately, the X-Client-Transaction-Id value is unobfuscated every day at 22:00 UTC.
How do I run the generator for TwitterInternalAPIDocument?
The README gives a single command, `uv run python generator.py`. The project is a uv managed Python project requiring Python 3.13 or newer, with requests, pandas, tabulate, tqdm, coloredlogs and pygithub as dependencies.
Is the internal API documentation in TwitterInternalAPIDocument accurate?
The README states the document is dedicated to automated analysis at the expense of accuracy, and points to the separate twitter-openapi repository for accurate documentation. It also says the repository is not complete and that this follows from the limitations of static code analysis.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fa0311-twitterinternalapidocument)Was this useful?