Created
January 31, 2026 13:49
-
-
Save cmj/c42675224da3e1ff642bf6c1616b9021 to your computer and use it in GitHub Desktop.
Find the last username change
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # requires auth_token. | |
| #auth_token="" | |
| source ~/.env-twitter | |
| screen_name=$1 | |
| usage() { echo -e "Show Twitter account location (requires auth_token)\n $0 <screen_name>"; exit 1; } | |
| [[ ! "$auth_token" || ! "$screen_name" ]] && usage | |
| # generate random ct0 | |
| x_csrf_token=$(tr -dc 0-9a-f < /dev/urandom | head -c 32) | |
| bearer_token='AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA' | |
| header=( | |
| -H "Authorization: Bearer ${bearer_token}" | |
| -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" | |
| -H "X-Csrf-Token: ${x_csrf_token}" | |
| -H "Cookie: ct0=${x_csrf_token}; auth_token=${auth_token}" | |
| ) | |
| url="https://x.com/i/api/graphql/XRqGa7EeokUU5kppkh13EA/AboutAccountQuery" | |
| variables='{"screenName":"'"${screen_name}"'"}' | |
| # quoted_user_id:122222313123 until:2025-11-07_18:21:04_UTC filter:media | |
| # or lang:qme ? | |
| query=$(curl -s -G "${header[@]}" "${url}" --data-urlencode "variables=${variables}" | jq -r '.data.user_result_by_screen_name.result | if(.about_profile.username_changes.last_changed_at_msec) then "quoted_user_id:\(.rest_id) \(.about_profile.username_changes.last_changed_at_msec[0:-3] | tonumber | strftime("until:%Y-%m-%d_%H:%M:%S_UTC")) filter:media" else null end') | |
| echo "search query: $query" | |
| if [[ "$query" == "null" ]]; then echo "No previous username found"; exit 1; fi | |
| ######## | |
| # search | |
| bearer_token='AAAAAAAAAAAAAAAAAAAAAFXzAwAAAAAAMHCxpeSDG1gLNLghVe8d74hl6k4%3DRUMF4xAQLsbeBhTSRrCiQpJtxoGWeyHrDb5te2jpGskWDFW82F' | |
| URL='https://api.twitter.com/graphql/gkjsKepM6gl_HmFWoWKfgg/SearchTimeline' | |
| VARIABLES='{"rawQuery":"'"${query}"'","count":1,"querySource":"typed_query","product":"Latest"}' | |
| FEATURES='{"android_graphql_skip_api_media_color_palette":false,"blue_business_profile_image_shape_enabled":false,"creator_subscriptions_subscription_count_enabled":false,"creator_subscriptions_tweet_preview_api_enabled":true,"freedom_of_speech_not_reach_fetch_enabled":false,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":false,"hidden_profile_likes_enabled":false,"highlights_tweets_tab_ui_enabled":false,"interactive_text_enabled":false,"longform_notetweets_consumption_enabled":true,"longform_notetweets_inline_media_enabled":false,"longform_notetweets_richtext_consumption_enabled":true,"longform_notetweets_rich_text_read_enabled":false,"responsive_web_edit_tweet_api_enabled":false,"responsive_web_enhance_cards_enabled":false,"responsive_web_graphql_exclude_directive_enabled":true,"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,"responsive_web_graphql_timeline_navigation_enabled":false,"responsive_web_media_download_video_enabled":false,"responsive_web_text_conversations_enabled":false,"responsive_web_twitter_article_tweet_consumption_enabled":false,"responsive_web_twitter_blue_verified_badge_is_enabled":true,"rweb_lists_timeline_redesign_enabled":true,"spaces_2022_h2_clipping":true,"spaces_2022_h2_spaces_communities":true,"standardized_nudges_misinfo":false,"subscriptions_verification_info_enabled":true,"subscriptions_verification_info_reason_enabled":true,"subscriptions_verification_info_verified_since_enabled":true,"super_follow_badge_privacy_enabled":false,"super_follow_exclusive_tweet_notifications_enabled":false,"super_follow_tweet_api_enabled":false,"super_follow_user_api_enabled":false,"tweet_awards_web_tipping_enabled":false,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":false,"tweetypie_unmention_optimization_enabled":false,"unified_cards_ad_metadata_container_dynamic_card_content_query_enabled":false,"verified_phone_label_enabled":false,"vibe_api_enabled":false,"view_counts_everywhere_api_enabled":false}' | |
| header=( | |
| -H "Authorization: Bearer ${bearer_token}" | |
| -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" | |
| -H "X-Csrf-Token: ${x_csrf_token}" | |
| -H "Cookie: ct0=${x_csrf_token}; auth_token=${auth_token}" | |
| ) | |
| # .quoted_status_result.result.legacy.extended_entities.media[0].expanded_url | |
| # .legacy.entities.urls[1].expanded_url | |
| curl -sG "${URL}" "${header[@]}" \ | |
| --data-urlencode "variables=${VARIABLES}" \ | |
| --data-urlencode "features=${FEATURES}" | | |
| jq -r '.data.search_by_raw_query.search_timeline.timeline.instructions[0].entries[0].content.itemContent.tweet_results.result | if (.legacy.entities.urls[1].expanded_url) then (.legacy.entities.urls[1].expanded_url | split("/")[3]) elif (.quoted_status_result.result.legacy.extended_entities.media[0].expanded_url) then (.quoted_status_result.result.legacy.extended_entities.media[0].expanded_url | split("/")[3]) else "Unable to find previous username" end' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment