Requests
These call any Jetfuel route directly, either raw or decoded.
client.jf(route, opts?)
The raw Jetfuel request, next to client.graphql, client.v1_1 and client.v2. It calls https://x.com/i/jfapi/<route> with the client's session, fingerprint and proxy, adds the Jetfuel headers x-jf-client-theme and x-jf-v, and returns the binary response. It needs a logged-in client. route is a path under /i/jfapi and can include a query string.
| Option | Type | Description |
|---|---|---|
params | object | Query parameters added to the URL |
method | string | Default "GET". actions/ routes need "POST". |
body | string | Request body for POST actions |
theme | string | x-jf-client-theme. Default "business". |
jfVersion | string | x-jf-v. Default "JP-5". |
headers | object | Extra headers, applied last |
referer | string | Referer. Default is the matching x.com/i/jf/<route> page. |
origin | string | "jfapi" (default) or "jf" to call https://jf.x.com/<route> instead |
It resolves to:
{
status, // HTTP status
headers, // response headers
contentType, // e.g. "text/plain"
buffer, // Node Buffer of the raw bytes
text(), // bytes as a UTF-8 string
decode(), // bytes decoded into the structured wire-format tree
}const res = await client.jf("creators/inspiration/remote/urt", {
params: { engagement: "Likes", period: "Daily", country: "USA" },
});
res.status; // 200
res.buffer.length // 173
res.decode(); // { frame, strings, nodes, atoms, lists, timelineTokens }jetfuel.page(route, opts?)
Fetches a route and decodes it in one call. Takes the same options as client.jf and returns the decoded payload plus status and contentType.
const studio = await client.jetfuel.page("creators/studio");
studio.frame; // { payloadLen, count, footer }
studio.strings; // every string in the page
studio.nodes; // [{ type, key }, ...]jetfuel.remote(route, opts?)
The same as page, named for remote/ data feeds.
const feed = await client.jetfuel.remote("creators/inspiration/remote/urt", {
params: { engagement: "Bookmarks", period: "Weekly" },
});
feed.timelineTokens; // ["VGltZWxpbmU6..."]jetfuel.raw(route, opts?)
Fetches a route and returns the client.jf result without decoding it, for when you want the bytes or the headers.
const res = await client.jetfuel.raw("creators/inspiration/top_posts");
res.buffer; // raw bytes
res.decode(); // decode on demandImage helpers
Jetfuel renders images of public tweets on the server. These helpers only build the URLs, and fetching them needs no login.
jetfuel.ogImageUrl(tweetId)
The Open Graph share card, a 1200x630 PNG with the avatar, name, badges, tweet text, media and the Twitter logo, always in the light theme. Private or deleted tweets return 404.
client.jetfuel.ogImageUrl("1895256113429241856");
// "https://jf.x.com/images/post/1895256113429241856"jetfuel.mediaPreviewUrl(tweetId)
A 1200x935 PNG of a tweet's attached media. Tweets without media return 404.
client.jetfuel.mediaPreviewUrl("1895256113429241856");
// "https://jf.x.com/images/media-preview/1895256113429241856"Other routes
Most Jetfuel routes describe UI rather than data, but you can fetch and inspect any of them:
await client.jetfuel.page("stories/home");
await client.jetfuel.page("creators/studio");
await client.jetfuel.page("nba/home");actions/ routes are POST mutations, and a GET returns a 400 or a validation message:
await client.jf("onboarding/actions/resendcode", { method: "POST", body: "..." });