twitter-openapi-typescript icon indicating copy to clipboard operation
twitter-openapi-typescript copied to clipboard

getTweetApi().getUserTweetsAndReplies by error 404

Open Bikapi-2020 opened this issue 8 months ago • 7 comments

getTweetApi().getUserTweetsAndReplies by error 404 but use getTweetApi().getUserTweets is ok why?

Error [ResponseError]: Response returned an error code at new ResponseError (/Users/Desktop/cs/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:405:28) at TweetApi. (/Users/Desktop/cs/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:325:31) at step (/Users/Desktop/cs/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:72:23) at Object.next (/Users/Desktop/cs/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:53:53) at fulfilled (/Users/Desktop/cs/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:44:58) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) { response: Response { size: 0, [Symbol(Body internals)]: { body: [PassThrough], stream: [PassThrough], boundary: null, disturbed: false, error: null }, [Symbol(Response internals)]: { type: 'default', url: 'https://x.com/i/api/graphql/pZXwh96YGRqmBbbxu7Vk2Q/UserTweetsAndReplies?variables=%7B%22userId%22%3A%22887281355037528064%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withVoice%22%3Atrue%2C%22withV2Timeline%22%3Atrue%7D&features=%7B%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22responsive_web_graphql_exclude_directive_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_analysis_button_from_backend%22%3Afalse%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%22rweb_video_timestamps_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', status: 404, statusText: 'Not Found', headers: [Object], counter: 0, highWaterMark: 16384 } } }

Bikapi-2020 avatar Apr 19 '25 01:04 Bikapi-2020

Please send me the minimal working program.

fa0311 avatar Apr 19 '25 06:04 fa0311

index.ts

import { TwitterOpenApiClient, TwitterOpenApi, type TwitterApiUtilsResponse, type TimelineApiUtilsResponse, type TweetApiUtilsData, type UserApiUtilsData } from 'twitter-openapi-typescript';
import { HttpsProxyAgent } from 'https-proxy-agent';
import fetch from 'node-fetch';

async function main() {
    // Initialize the Twitter API 
    const cookie = { auth_token: '', ct0: '' };

    const api = new TwitterOpenApi();
    TwitterOpenApi.fetchApi = fetch as any;

    // const proxyAgent = new HttpsProxyAgent('http://127.0.0.1:7890');
    // api.setInitOverrides({ agent: proxyAgent } as any);
    // const client = await api.getGuestClient();
    const client = await api.getClientFromCookies(cookie);
    // console.log(client);

    try{
        const res1 = await client.getTweetApi().getUserTweets({ userId: '887281355037528064'});
        console.log(res1.data);
        const res2 = await client.getTweetApi().getUserTweetsAndReplies({ userId: '887281355037528064' });
        console.log(res2);
        
    }catch(e){
        console.log('error message: ',e);
    }
    // const res = await client.getPostApi().postCreateTweet({
    //     tweetText: 'Hello World!!',
    // });
    // console.log(res.data.data.createTweet?.tweetResults);

}

main();

package.json

{
  "name": "cs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@types/node": "^22.14.1",
    "https-proxy-agent": "^7.0.6",
    "node-fetch": "^3.3.2",
    "ts-node": "^10.9.2",
    "twitter-api-v2": "^1.22.0",
    "twitter-openapi-typescript": "^0.0.51",
    "typescript": "^5.8.3"
  }
}

error message

error message:  Error [ResponseError]: Response returned an error code
    at new ResponseError (/Users/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:405:28)
    at TweetApi.<anonymous> (/Users/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:325:31)
    at step (/Users/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:72:23)
    at Object.next (/Users/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:53:53)
    at fulfilled (/Users/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:44:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
  response: Response {
    size: 0,
    timeout: 0,
    [Symbol(Body internals)]: { body: [PassThrough], disturbed: false, error: null },
    [Symbol(Response internals)]: {
      url: 'https://x.com/i/api/graphql/HmWGzuzXoI6uFqqX6QNhEg/UserTweetsAndReplies?variables=%7B%22userId%22%3A%22887281355037528064%22%2C%22count%22%3A40%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withVoice%22%3Atrue%2C%22withV2Timeline%22%3Atrue%7D&features=%7B%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22responsive_web_graphql_exclude_directive_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%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_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%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%22rweb_video_timestamps_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D',
      status: 404,
      statusText: 'Not Found',
      headers: [Headers],
      counter: 0
    }
  }
}

Bikapi-2020 avatar Apr 19 '25 11:04 Bikapi-2020

I have the same problem, has it been solved now?

jiayuxiaochaoren avatar Apr 26 '25 12:04 jiayuxiaochaoren

I'm the same way.

moons-14 avatar Apr 27 '25 12:04 moons-14

I am currently working on this issue.

fa0311 avatar Apr 27 '25 16:04 fa0311

I am currently working on this issue.

if it helps, some other methods return 404 as well. Like '/api/tweets/:tweetId/like' and /SearchTimeline

kingkej avatar Apr 28 '25 05:04 kingkej

Has it been solved?

y1834257499 avatar Apr 28 '25 13:04 y1834257499

getUserTweetsAndReplies is not fixed, but other APIs are fixed However, it is not a very good implementation...

fa0311 avatar Apr 29 '25 15:04 fa0311

getUserTweetsAndReplies is not fixed, but other APIs are fixed However, it is not a very good implementation...

what did cause this problem? I see you have added tid generation to dev branch, as well as some cookies adjustments.

kingkej avatar Apr 29 '25 15:04 kingkej

@kingkej

The issue is caused by Twitter introducing a new anti-bot system requiring a unique x-client-transaction-id header for each request. This ID is generated through a highly obfuscated client-side mechanism that emulates CSS Bézier curve rendering.

I’ve implemented a workaround that doesn’t emulate Bézier curves but instead generates the ID using keys exported from a real browser session. While this works, it’s admittedly not a clean or sustainable solution, so I plan to switch to proper Bézier emulation in the future.

If you're curious about how this mechanism works, you can check out the following resources:

  • https://github.com/fa0311/antibot_blog_archives
  • https://blog.nest.moe/posts/twitter-header-part-4

For details on my current implementation:

  • https://github.com/fa0311/x-client-transaction-id-pair-dict
  • https://github.com/fa0311/x-client-transaction-id-generater

As for the issue with getUserTweetsAndReplies not being fixed — this is because Twitter has made a direct change to that specific API.
Since my work is mainly based on Python, please wait until I implement a key generation program in Python.

fa0311 avatar Apr 29 '25 15:04 fa0311

@fa0311 thanks! I will dig into it. Also recently I have found new repo with tid generation, you should look, maybe it will help somehow: https://github.com/Lqm1/x-client-transaction-id

kingkej avatar Apr 29 '25 15:04 kingkej

@kingkej JavaScript(Node) has significant floating-point inaccuracies, so simply replacing a Go implementation won't work as expected. This repository is no exception—it doesn't work correctly either.

fa0311 avatar Apr 29 '25 15:04 fa0311

@kingkej JavaScript(Node) has significant floating-point inaccuracies, so simply replacing a Go implementation won't work as expected. This repository is no exception—it doesn't work correctly either.

thank you for explanation and your work & open source contribution! really appreciate it =)

kingkej avatar Apr 29 '25 15:04 kingkej

@fa0311 after updating to "twitter-openapi-typescript": "^0.0.53" 404 sometimes still happens on like and search timeline:

xparser-1  | Error while liking tweet: Error [ResponseError]: Response returned an error code
xparser-1  |     at new ResponseError (/build/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:405:28)
xparser-1  |     at PostApi.<anonymous> (/build/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:325:31)
xparser-1  |     at step (/build/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:72:23)
xparser-1  |     at Object.next (/build/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:53:53)
xparser-1  |     at fulfilled (/build/node_modules/twitter-openapi-typescript-generated/dist/runtime.js:44:58)
xparser-1  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
xparser-1  |   response: Response {
xparser-1  |     size: 0,
xparser-1  |     [Symbol(Body internals)]: {
xparser-1  |       body: [PassThrough],
xparser-1  |       stream: [PassThrough],
xparser-1  |       boundary: null,
xparser-1  |       disturbed: false,
xparser-1  |       error: null
xparser-1  |     },
xparser-1  |     [Symbol(Response internals)]: {
xparser-1  |       type: 'default',
xparser-1  |       url: 'https://x.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet',
xparser-1  |       status: 404,
xparser-1  |       statusText: 'Not Found',
xparser-1  |       headers: [Object],
xparser-1  |       counter: 0,
xparser-1  |       highWaterMark: 16384
xparser-1  |     }
xparser-1  |   }
xparser-1  | }

kingkej avatar Apr 29 '25 20:04 kingkej

This issue has been fixed.

fa0311 avatar May 07 '25 16:05 fa0311