Skip to content

Instantly share code, notes, and snippets.

@cmj
Last active December 29, 2025 22:54
Show Gist options
  • Select an option

  • Save cmj/ee6ed87e2835864b7ead3b0d7e5edb0f to your computer and use it in GitHub Desktop.

Select an option

Save cmj/ee6ed87e2835864b7ead3b0d7e5edb0f to your computer and use it in GitHub Desktop.
Twitter rate-limit search test
#!/usr/bin/env bash
# Twitter rate-limit search test
# ./search.sh <auth_token>
auth_token=$1
x_csrf_token=$(openssl rand -hex 16)
query="fish"
product="Latest" # Latest | Top
count=1 # 1-20
####
if [[ -z "$auth_token" ]]; then echo "requires auth_token"; exit 1; fi
#bearer_token='AAAAAAAAAAAAAAAAAAAAAIWCCAAAAAAA2C25AxqI%2BYCS7pdfJKRH8Xh19zA%3D8vpDZzPHaEJhd20MKVWp3UR38YoPpuTX7UD2cVYo3YNikubuxd'
bearer_token='AAAAAAAAAAAAAAAAAAAAAFXzAwAAAAAAMHCxpeSDG1gLNLghVe8d74hl6k4%3DRUMF4xAQLsbeBhTSRrCiQpJtxoGWeyHrDb5te2jpGskWDFW82F'
URL='https://api.twitter.com/graphql/gkjsKepM6gl_HmFWoWKfgg/SearchTimeline'
VARIABLES='{"rawQuery":"'"${query}"'","count":'"${count}"',"querySource":"typed_query","product":"'"${product}"'"}'
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}"
)
output=$(curl -svG "${URL}" "${header[@]}" \
--data-urlencode "variables=${VARIABLES}" \
--data-urlencode "features=${FEATURES}" 2>&1 |
egrep '^< x-rate|^\{"')
tail -1 <<< "${output}" #| jq -c
echo '-----'
sed -En -e 's/^< x-rate-limit-.*: (.*)\r/\1/p' <<< "${output}" | sort -n | xargs | while read remaining limit reset; do echo -e "limit: \x1b[32m$remaining/$limit\x1b[0m reset: \x1b[94m$(date -d@$reset '+%a %T')\x1b[0m"; done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment