@the-convocation/twitter-scraper 0.18.3 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dist/cycletls/cjs/index.cjs +99 -0
- package/dist/cycletls/cjs/index.cjs.map +1 -0
- package/dist/cycletls/esm/index.mjs +96 -0
- package/dist/cycletls/esm/index.mjs.map +1 -0
- package/dist/cycletls/index.d.ts +11 -0
- package/dist/default/cjs/index.js +100 -25
- package/dist/default/cjs/index.js.map +1 -1
- package/dist/default/esm/index.mjs +100 -25
- package/dist/default/esm/index.mjs.map +1 -1
- package/dist/node/cjs/index.cjs +100 -25
- package/dist/node/cjs/index.cjs.map +1 -1
- package/dist/node/esm/index.mjs +100 -25
- package/dist/node/esm/index.mjs.map +1 -1
- package/examples/cycletls/README.md +48 -0
- package/examples/cycletls/package.json +13 -0
- package/package.json +25 -9
- package/rollup.config.mjs +34 -0
package/dist/node/cjs/index.cjs
CHANGED
|
@@ -72,13 +72,13 @@ class AuthenticationError extends Error {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const log$
|
|
75
|
+
const log$4 = debug("twitter-scraper:rate-limit");
|
|
76
76
|
class WaitingRateLimitStrategy {
|
|
77
77
|
async onRateLimit({ response: res }) {
|
|
78
78
|
const xRateLimitLimit = res.headers.get("x-rate-limit-limit");
|
|
79
79
|
const xRateLimitRemaining = res.headers.get("x-rate-limit-remaining");
|
|
80
80
|
const xRateLimitReset = res.headers.get("x-rate-limit-reset");
|
|
81
|
-
log$
|
|
81
|
+
log$4(
|
|
82
82
|
`Rate limit event: limit=${xRateLimitLimit}, remaining=${xRateLimitRemaining}, reset=${xRateLimitReset}`
|
|
83
83
|
);
|
|
84
84
|
if (xRateLimitRemaining == "0" && xRateLimitReset) {
|
|
@@ -107,16 +107,47 @@ class Platform {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
const log$3 = debug("twitter-scraper:requests");
|
|
110
111
|
async function updateCookieJar(cookieJar, headers) {
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
let setCookieHeaders = [];
|
|
113
|
+
if (typeof headers.getSetCookie === "function") {
|
|
114
|
+
setCookieHeaders = headers.getSetCookie();
|
|
115
|
+
} else {
|
|
116
|
+
const setCookieHeader = headers.get("set-cookie");
|
|
117
|
+
if (setCookieHeader) {
|
|
118
|
+
setCookieHeaders = setCookie.splitCookiesString(setCookieHeader);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (setCookieHeaders.length > 0) {
|
|
122
|
+
for (const cookieStr of setCookieHeaders) {
|
|
123
|
+
const cookie = toughCookie.Cookie.parse(cookieStr);
|
|
124
|
+
if (!cookie) {
|
|
125
|
+
log$3(`Failed to parse cookie: ${cookieStr.substring(0, 100)}`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (cookie.maxAge === 0 || cookie.expires && cookie.expires < /* @__PURE__ */ new Date()) {
|
|
129
|
+
if (cookie.key === "ct0") {
|
|
130
|
+
log$3(`Skipping deletion of ct0 cookie (Max-Age=0)`);
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const url = `${cookie.secure ? "https" : "http"}://${cookie.domain}${cookie.path}`;
|
|
136
|
+
await cookieJar.setCookie(cookie, url);
|
|
137
|
+
if (cookie.key === "ct0") {
|
|
138
|
+
log$3(
|
|
139
|
+
`Successfully set ct0 cookie with value: ${cookie.value.substring(
|
|
140
|
+
0,
|
|
141
|
+
20
|
|
142
|
+
)}...`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
log$3(`Failed to set cookie ${cookie.key}: ${err}`);
|
|
147
|
+
if (cookie.key === "ct0") {
|
|
148
|
+
log$3(`FAILED to set ct0 cookie! Error: ${err}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
120
151
|
}
|
|
121
152
|
} else if (typeof document !== "undefined") {
|
|
122
153
|
for (const cookie of document.cookie.split(";")) {
|
|
@@ -134,9 +165,8 @@ async function jitter(maxMs) {
|
|
|
134
165
|
const jitter2 = Math.random() * maxMs;
|
|
135
166
|
await new Promise((resolve) => setTimeout(resolve, jitter2));
|
|
136
167
|
}
|
|
137
|
-
async function requestApi(url, auth, method = "GET", platform = new Platform()) {
|
|
168
|
+
async function requestApi(url, auth, method = "GET", platform = new Platform(), headers = new headersPolyfill.Headers()) {
|
|
138
169
|
log$2(`Making ${method} request to ${url}`);
|
|
139
|
-
const headers = new headersPolyfill.Headers();
|
|
140
170
|
await auth.installTo(headers, url);
|
|
141
171
|
await platform.randomizeCiphers();
|
|
142
172
|
let res;
|
|
@@ -175,7 +205,7 @@ async function requestApi(url, auth, method = "GET", platform = new Platform())
|
|
|
175
205
|
err: await ApiError.fromResponse(res)
|
|
176
206
|
};
|
|
177
207
|
}
|
|
178
|
-
const value = await res
|
|
208
|
+
const value = await flexParseJson(res);
|
|
179
209
|
if (res.headers.get("x-rate-limit-incoming") == "0") {
|
|
180
210
|
auth.deleteToken();
|
|
181
211
|
return { success: true, value };
|
|
@@ -183,6 +213,16 @@ async function requestApi(url, auth, method = "GET", platform = new Platform())
|
|
|
183
213
|
return { success: true, value };
|
|
184
214
|
}
|
|
185
215
|
}
|
|
216
|
+
async function flexParseJson(res) {
|
|
217
|
+
try {
|
|
218
|
+
return await res.json();
|
|
219
|
+
} catch {
|
|
220
|
+
log$2("Failed to parse response as JSON, trying text parse...");
|
|
221
|
+
const text = await res.text();
|
|
222
|
+
log$2("Response text:", text);
|
|
223
|
+
return JSON.parse(text);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
186
226
|
function addApiFeatures(o) {
|
|
187
227
|
return {
|
|
188
228
|
...o,
|
|
@@ -315,6 +355,10 @@ class TwitterGuestAuth {
|
|
|
315
355
|
}
|
|
316
356
|
headers.set("authorization", `Bearer ${this.bearerToken}`);
|
|
317
357
|
headers.set("x-guest-token", token);
|
|
358
|
+
headers.set(
|
|
359
|
+
"user-agent",
|
|
360
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
|
|
361
|
+
);
|
|
318
362
|
const cookies = await this.getCookies();
|
|
319
363
|
const xCsrfToken = cookies.find((cookie) => cookie.key === "ct0");
|
|
320
364
|
if (xCsrfToken) {
|
|
@@ -322,6 +366,16 @@ class TwitterGuestAuth {
|
|
|
322
366
|
}
|
|
323
367
|
headers.set("cookie", await this.getCookieString());
|
|
324
368
|
}
|
|
369
|
+
async setCookie(key, value) {
|
|
370
|
+
const cookie = toughCookie.Cookie.parse(`${key}=${value}`);
|
|
371
|
+
if (!cookie) {
|
|
372
|
+
throw new Error("Failed to parse cookie.");
|
|
373
|
+
}
|
|
374
|
+
await this.jar.setCookie(cookie, this.getCookieJarUrl());
|
|
375
|
+
if (typeof document !== "undefined") {
|
|
376
|
+
document.cookie = cookie.toString();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
325
379
|
async getCookies() {
|
|
326
380
|
return this.jar.getCookies(this.getCookieJarUrl());
|
|
327
381
|
}
|
|
@@ -362,7 +416,7 @@ class TwitterGuestAuth {
|
|
|
362
416
|
if (!res.ok) {
|
|
363
417
|
throw new AuthenticationError(await res.text());
|
|
364
418
|
}
|
|
365
|
-
const o = await res
|
|
419
|
+
const o = await flexParseJson(res);
|
|
366
420
|
if (o == null || o["guest_token"] == null) {
|
|
367
421
|
throw new AuthenticationError("guest_token not found.");
|
|
368
422
|
}
|
|
@@ -372,6 +426,8 @@ class TwitterGuestAuth {
|
|
|
372
426
|
}
|
|
373
427
|
this.guestToken = newGuestToken;
|
|
374
428
|
this.guestCreatedAt = /* @__PURE__ */ new Date();
|
|
429
|
+
await this.setCookie("gt", newGuestToken);
|
|
430
|
+
log$1(`Updated guest token: ${newGuestToken}`);
|
|
375
431
|
}
|
|
376
432
|
/**
|
|
377
433
|
* Returns if the authentication token needs to be updated or not.
|
|
@@ -498,7 +554,15 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
498
554
|
}
|
|
499
555
|
async installTo(headers) {
|
|
500
556
|
headers.set("authorization", `Bearer ${this.bearerToken}`);
|
|
501
|
-
|
|
557
|
+
const cookie = await this.getCookieString();
|
|
558
|
+
headers.set("cookie", cookie);
|
|
559
|
+
if (this.guestToken) {
|
|
560
|
+
headers.set("x-guest-token", this.guestToken);
|
|
561
|
+
}
|
|
562
|
+
headers.set(
|
|
563
|
+
"user-agent",
|
|
564
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
|
|
565
|
+
);
|
|
502
566
|
await this.installCsrfToken(headers);
|
|
503
567
|
}
|
|
504
568
|
async initLogin() {
|
|
@@ -711,16 +775,27 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
711
775
|
);
|
|
712
776
|
}
|
|
713
777
|
const headers = new headersPolyfill.Headers({
|
|
714
|
-
|
|
715
|
-
|
|
778
|
+
accept: "*/*",
|
|
779
|
+
"accept-language": "en-US,en;q=0.9",
|
|
716
780
|
"content-type": "application/json",
|
|
717
|
-
"
|
|
781
|
+
"cache-control": "no-cache",
|
|
782
|
+
origin: "https://x.com",
|
|
783
|
+
pragma: "no-cache",
|
|
784
|
+
priority: "u=1, i",
|
|
785
|
+
referer: "https://x.com/",
|
|
786
|
+
"sec-ch-ua": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
|
|
787
|
+
"sec-ch-ua-mobile": "?0",
|
|
788
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
789
|
+
"sec-fetch-dest": "empty",
|
|
790
|
+
"sec-fetch-mode": "cors",
|
|
791
|
+
"sec-fetch-site": "same-origin",
|
|
792
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
|
718
793
|
"x-guest-token": token,
|
|
719
794
|
"x-twitter-auth-type": "OAuth2Client",
|
|
720
795
|
"x-twitter-active-user": "yes",
|
|
721
796
|
"x-twitter-client-language": "en"
|
|
722
797
|
});
|
|
723
|
-
await this.
|
|
798
|
+
await this.installTo(headers);
|
|
724
799
|
let res;
|
|
725
800
|
do {
|
|
726
801
|
const fetchParameters = [
|
|
@@ -755,7 +830,7 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
755
830
|
if (!res.ok) {
|
|
756
831
|
return { status: "error", err: await ApiError.fromResponse(res) };
|
|
757
832
|
}
|
|
758
|
-
const flow = await res
|
|
833
|
+
const flow = await flexParseJson(res);
|
|
759
834
|
if (flow?.flow_token == null) {
|
|
760
835
|
return {
|
|
761
836
|
status: "error",
|
|
@@ -793,12 +868,12 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
793
868
|
|
|
794
869
|
const endpoints = {
|
|
795
870
|
// TODO: Migrate other endpoint URLs here
|
|
796
|
-
UserTweets: "https://
|
|
871
|
+
UserTweets: "https://x.com/i/api/graphql/oRJs8SLCRNRbQzuZG93_oA/UserTweets?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
|
|
797
872
|
UserTweetsAndReplies: "https://x.com/i/api/graphql/Hk4KlJ-ONjlJsucqR55P7g/UserTweetsAndReplies?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
|
|
798
873
|
UserLikedTweets: "https://x.com/i/api/graphql/XHTMjDbiTGLQ9cP1em-aqQ/Likes?variables=%7B%22userId%22%3A%222244196397%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withClientEventToken%22%3Afalse%2C%22withBirdwatchNotes%22%3Afalse%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
|
|
799
|
-
UserByScreenName: "https://
|
|
800
|
-
TweetDetail: "https://x.com/i/api/graphql/
|
|
801
|
-
TweetResultByRestId: "https://api.x.com/graphql/
|
|
874
|
+
UserByScreenName: "https://x.com/i/api/graphql/ZHSN3WlvahPKVvUxVQbg1A/UserByScreenName?variables=%7B%22screen_name%22%3A%22geminiapp%22%2C%22withGrokTranslatedBio%22%3Atrue%7D&features=%7B%22hidden_profile_subscriptions_enabled%22%3Atrue%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22subscriptions_verification_info_is_identity_verified_enabled%22%3Atrue%2C%22subscriptions_verification_info_verified_since_enabled%22%3Atrue%2C%22highlights_tweets_tab_ui_enabled%22%3Atrue%2C%22responsive_web_twitter_article_notes_tab_enabled%22%3Atrue%2C%22subscriptions_feature_can_gift_premium%22%3Atrue%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%7D&fieldToggles=%7B%22withAuxiliaryUserLabels%22%3Atrue%7D",
|
|
875
|
+
TweetDetail: "https://x.com/i/api/graphql/YVyS4SfwYW7Uw5qwy0mQCA/TweetDetail?variables=%7B%22focalTweetId%22%3A%221985465713096794294%22%2C%22referrer%22%3A%22profile%22%2C%22with_rux_injections%22%3Afalse%2C%22rankingMode%22%3A%22Relevance%22%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withBirdwatchNotes%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D",
|
|
876
|
+
TweetResultByRestId: "https://api.x.com/graphql/tCVRZ3WCvoj0BVO7BKnL-Q/TweetResultByRestId?variables=%7B%22tweetId%22%3A%221985465713096794294%22%2C%22withCommunity%22%3Afalse%2C%22includePromotedContent%22%3Afalse%2C%22withVoice%22%3Afalse%7D&features=%7B%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Afalse%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D",
|
|
802
877
|
ListTweets: "https://x.com/i/api/graphql/S1Sm3_mNJwa-fnY9htcaAQ/ListLatestTweetsTimeline?variables=%7B%22listId%22%3A%221736495155002106192%22%2C%22count%22%3A20%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D"
|
|
803
878
|
};
|
|
804
879
|
class ApiRequest {
|