Requests
Beyond the top-posts helpers, emusks gives you a low-level request primitive and thin fetch-and-decode wrappers so you can hit any Jetfuel route directly.
client.jf(route, opts?)
The low-level primitive, alongside client.graphql, client.v1_1 and client.v2. It hits https://x.com/i/jfapi/<route> with the same auth, fingerprint and proxy plumbing as the rest of the library, adds the Jetfuel-specific headers (x-jf-client-theme, x-jf-v), and returns the raw binary response.
| Option | Type | Description |
|---|---|---|
route | string | Path under /i/jfapi (may include a query string). |
opts.params | object | Query params (merged into the URL). |
opts.method | string | HTTP method (default "GET"; use "POST" for actions/ routes). |
opts.body | string | Request body for POST actions. |
opts.theme | string | x-jf-client-theme value (default "business"). |
opts.jfVersion | string | x-jf-v value (default "JP-5"). |
opts.headers | object | Extra headers (merged last). |
opts.referer | string | Override the Referer (defaults to the matching i/jf mount). |
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?)
Fetch a route and decode its binary payload into JSON in one call. Same options as client.jf. Returns the decoded wire format 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?)
Alias for page, named to read better when fetching 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?)
Fetch a route and return the raw response (the client.jf result) without decoding. Use this when you want the bytes, the headers, or to decode later.
const res = await client.jetfuel.raw("creators/inspiration/top_posts");
res.buffer; // raw bytes
res.decode(); // decode on demandImage helpers
Jetfuel also server-renders images for any public tweet. These helpers return the URLs (no auth needed to fetch them).
jetfuel.ogImageUrl(tweetId)
The Open Graph share card (1200x630 PNG): avatar, name, verified/affiliate badge, tweet text, media and the X logo. Always light theme. Private or deleted tweets return 404.
client.jetfuel.ogImageUrl("1895256113429241856");
// "https://jf.x.com/images/post/1895256113429241856"jetfuel.mediaPreviewUrl(tweetId)
A PNG re-render of a tweet's attached media (1200x935). Returns 404 for tweets with no media.
client.jetfuel.mediaPreviewUrl("1895256113429241856");
// "https://jf.x.com/images/media-preview/1895256113429241856"Other routes
The Jetfuel surface is large (the Creator hub, Stories, the sports and live-events hub, onboarding). Most routes are pure UI rather than data feeds, 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. A bare GET returns a 400 or a validation message:
await client.jf("onboarding/actions/resendcode", { method: "POST", body: "..." });