TwitterユーザーID取得

    @@ -7,73 +7,138 @@ * @javascript_url */ -( () => { +(async () => { 'use strict'; -let screen_name = window.getSelection().toString() || prompt( 'Input screen name of user', '' ); +const error_alert = (error_message) => { + console.error(error_message); + alert(error_message); +}; -if ( screen_name === null ) return; -screen_name = screen_name.trim().replace( /^@/, '' ); -if ( ! screen_name ) return; - -fetch( 'https://api.twitter.com/1.1/users/show.json?screen_name=' + encodeURIComponent( screen_name ), { - method: 'GET', - headers: { - 'authorization' : 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA', - 'x-csrf-token' : document.cookie.match( /ct0=(.*?)(?:;|$)/ )[ 1 ], - 'x-twitter-active-user' : 'yes', - 'x-twitter-auth-type' : 'OAuth2Session', - 'x-twitter-client-language' : 'en', - }, - mode: 'cors', - credentials : 'include', -} ) -.then( response => { - if ( ! response.ok ) { - throw new Error( 'Network response was not ok' ); - } - return response.json() -} ) -.then( user_info => { - let user_id = user_info.id_str; - - if ( ! user_id ) { - throw new Error( 'Response does not include the ID of the user' ); +let screen_name = window.getSelection().toString() || prompt('Input screen-name of user', ''); +if (screen_name === null) return; +screen_name = screen_name.trim().replace(/^@/, ''); +if (! screen_name) { + error_alert('screen-name is empty'); + return; +} + +const api_info = await (async () => { + try { + const main_js_url = document.querySelector('link[as="script"][href*="main"]')?.href ?? document.querySelector('script[src*="main"][src$=".js"]')?.src; + if (! main_js_url) { + throw new Error(`URL of main*.js is not found`); + } + const response = await fetch(main_js_url); + if (! response.ok) { + throw new Error(`HTTP response status code=${response.status}`); + } + const main_js_text = await response.text(); + const api_info_json = main_js_text.match(/\{e\.exports=(\{[^}]*?operationName:"UserByScreenName"[\s\S]*?\})\},\d+:e=>\{e.exports/)[1].replace(/(\w+)(?=:)/g, '"$1"'); + const api_info = JSON.parse(api_info_json); + return api_info; + } + catch (error) { + error_alert(`Fetch API-Information failure: ${error}`); + return null; } +})(); +if (! api_info) return; + +const user_id = await (async () => { + const base_url = `https://x.com/i/api/graphql/${api_info.queryId}/UserByScreenName`; + const api2_auth_bearer = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'; + const csrf_token = document.cookie.match(/ct0=(.*?)(?:;|$)/)[1]; + const search_params = { + variables: { + "screen_name": screen_name, + "withGrokTranslatedBio": false + }, + features: { + "hidden_profile_subscriptions_enabled": true, + "profile_label_improvements_pcf_label_in_post_enabled": true, + "responsive_web_profile_redirect_enabled": false, + "rweb_tipjar_consumption_enabled": false, + "verified_phone_label_enabled": false, + "subscriptions_verification_info_is_identity_verified_enabled": true, + "subscriptions_verification_info_verified_since_enabled": true, + "highlights_tweets_tab_ui_enabled": true, + "responsive_web_twitter_article_notes_tab_enabled": true, + "subscriptions_feature_can_gift_premium": true, + "creator_subscriptions_tweet_preview_api_enabled": true, + "responsive_web_graphql_skip_user_profile_image_extensions_enabled": false, + "responsive_web_graphql_timeline_navigation_enabled": true + }, + fieldToggles: { + "withPayments": false, + "withAuxiliaryUserLabels": true + }, + }; + const url_object = new URL(base_url); + Object.entries(search_params).forEach(([key, value]) => { + url_object.searchParams.append(key, JSON.stringify(value)); + }); - navigator.clipboard.writeText( user_id ) - .then( () => { - } ) - .catch( error => { - console.error( 'Copy result to clipboard failure:', error ); - } ) - .finally( () => { - let prompt_required = true; + try { + const response = await fetch(url_object.href, { + method: 'GET', + headers: { + 'authorization': `Bearer ${api2_auth_bearer}`, + 'x-csrf-token': csrf_token, + 'x-twitter-active-user': 'yes', + 'x-twitter-auth-type': 'OAuth2Session', + 'x-twitter-client-language': 'en', + }, + mode: 'cors', + credentials: 'include', + }); + if (! response.ok) { + throw new Error(`HTTP response status code=${response.status}`); + } + const user_info = await response.json(); + const user_id = user_info?.data?.user?.result?.rest_id; - try { - let target = window.getSelection().anchorNode.children[ 0 ]; - - if ( target.tagName == 'INPUT' ) { - let event = new Event( 'input', { bubbles : true } ), - tracker = target._valueTracker, - last_value = target.value, - new_value = last_value.substring( 0, target.selectionStart ) + user_id + last_value.substring( target.selectionEnd ); - - target.value = new_value; - event.simulated = true; - if ( tracker ) tracker.setValue( last_value ); - target.dispatchEvent( event ); - prompt_required = false; - } + if (! user_id) { + throw new Error('Response does not include the ID of the user'); } - catch ( error ) { + return user_id; + } + catch (error) { + error_alert(`"${screen_name}" is not found: ${error}`); + return null; + } + +})(); +if (! user_id) return; + +try { + await navigator.clipboard.writeText(user_id); +} +catch (error) { + console.error(`Copy result to clipboard failure: ${error}`); +} +finally { + let prompt_required = true; + try { + const target = window.getSelection().anchorNode.children[0]; + if (target.tagName == 'INPUT') { + const event = new Event('input', {bubbles: true}); + const tracker = target._valueTracker; + const last_value = target.value; + const new_value = last_value.substring(0, target.selectionStart) + user_id + last_value.substring(target.selectionEnd); + + target.value = new_value; + event.simulated = true; + if (tracker) tracker.setValue(last_value); + target.dispatchEvent(event); + prompt_required = false; } - - if ( prompt_required ) prompt( 'User ID of ' + screen_name, user_id ); - } ); -} ) -.catch( error => { - console.error( screen_name, error ); - alert( '"' + screen_name + '" is not found: ' + error ); -} ); -} )(); + } + catch (error) { + console.error(`Failed to rewrite screen name to user ID: ${error}`); + } + if ( prompt_required ) { + prompt(`User ID of ${screen_name}`, user_id); + } +} +})();
  • /*
     * @title TwitterユーザーID取得
     * @description Twitterユーザーのscreen_nameからユーザーIDを取得する
     * @include https://twitter.com/*
     * @license MIT License
     * @require 
     * @javascript_url
     */
    
    (async () => {
    'use strict';
    
    const error_alert = (error_message) => {
        console.error(error_message);
        alert(error_message);
    };
    
    let screen_name = window.getSelection().toString() || prompt('Input screen-name of user', '');
    if (screen_name === null) return;
    screen_name = screen_name.trim().replace(/^@/, '');
    if (! screen_name) {
        error_alert('screen-name is empty');
        return;
    }
    
    const api_info = await (async () => {
        try {
            const main_js_url = document.querySelector('link[as="script"][href*="main"]')?.href ?? document.querySelector('script[src*="main"][src$=".js"]')?.src;
            if (! main_js_url) {
                throw new Error(`URL of main*.js is not found`);
            }
            const response = await fetch(main_js_url);
            if (! response.ok) {
                throw new Error(`HTTP response status code=${response.status}`);
            }
            const main_js_text = await response.text();
            const api_info_json = main_js_text.match(/\{e\.exports=(\{[^}]*?operationName:"UserByScreenName"[\s\S]*?\})\},\d+:e=>\{e.exports/)[1].replace(/(\w+)(?=:)/g, '"$1"');
            const api_info = JSON.parse(api_info_json);
            return api_info;
        }
        catch (error) {
            error_alert(`Fetch API-Information failure: ${error}`);
            return null;
        }
    })();
    if (! api_info) return;
    
    const user_id = await (async () => {
        const base_url = `https://x.com/i/api/graphql/${api_info.queryId}/UserByScreenName`;
        const api2_auth_bearer = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
        const csrf_token = document.cookie.match(/ct0=(.*?)(?:;|$)/)[1];
        const search_params = {
            variables: {
                "screen_name": screen_name,
                "withGrokTranslatedBio": false
            },
            features: {
                "hidden_profile_subscriptions_enabled": true,
                "profile_label_improvements_pcf_label_in_post_enabled": true,
                "responsive_web_profile_redirect_enabled": false,
                "rweb_tipjar_consumption_enabled": false,
                "verified_phone_label_enabled": false,
                "subscriptions_verification_info_is_identity_verified_enabled": true,
                "subscriptions_verification_info_verified_since_enabled": true,
                "highlights_tweets_tab_ui_enabled": true,
                "responsive_web_twitter_article_notes_tab_enabled": true,
                "subscriptions_feature_can_gift_premium": true,
                "creator_subscriptions_tweet_preview_api_enabled": true,
                "responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
                "responsive_web_graphql_timeline_navigation_enabled": true
            },
            fieldToggles: {
                "withPayments": false,
                "withAuxiliaryUserLabels": true
            },
        };
        const url_object = new URL(base_url);
        Object.entries(search_params).forEach(([key, value]) => {
            url_object.searchParams.append(key, JSON.stringify(value));
        });
        
        try {
            const response = await fetch(url_object.href, {
                method: 'GET',
                headers: {
                    'authorization': `Bearer ${api2_auth_bearer}`,
                    'x-csrf-token': csrf_token,
                    'x-twitter-active-user': 'yes',
                    'x-twitter-auth-type': 'OAuth2Session',
                    'x-twitter-client-language': 'en',
                },
                mode: 'cors',
                credentials: 'include',
            });
            if (! response.ok) {
                throw new Error(`HTTP response status code=${response.status}`);
            }
            const user_info = await response.json();
            const user_id = user_info?.data?.user?.result?.rest_id;
            
            if (! user_id) {
                throw new Error('Response does not include the ID of the user');
            }
            return user_id;
        }
        catch (error) {
            error_alert(`"${screen_name}" is not found: ${error}`);
            return null;
        }
        
    })();
    if (! user_id) return;
    
    try {
        await navigator.clipboard.writeText(user_id);
    }
    catch (error) {
        console.error(`Copy result to clipboard failure: ${error}`);
    }
    finally {
        let prompt_required = true;
        try {
            const target = window.getSelection().anchorNode.children[0];
            if (target.tagName == 'INPUT') {
                const event = new Event('input', {bubbles: true});
                const tracker = target._valueTracker;
                const last_value = target.value;
                const new_value = last_value.substring(0, target.selectionStart) + user_id + last_value.substring(target.selectionEnd);
                
                target.value = new_value;
                event.simulated = true;
                if (tracker) tracker.setValue(last_value);
                target.dispatchEvent(event);
                prompt_required = false;
            }
        }
        catch (error) {
            console.error(`Failed to rewrite screen name to user ID: ${error}`);
        }
        if ( prompt_required ) {
            prompt(`User ID of ${screen_name}`, user_id);
        }
    }
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2026/01/29 20:10:49 - 01/29
  2. 2020/10/30 01:48:24 - 2020-10-30
  3. 2020/10/30 01:42:17 - 2020-10-30
  4. 2020/10/30 01:40:12 - 2020-10-30
  5. 2020/10/29 17:34:00 - 2020-10-29
  6. 2020/10/29 17:06:47 - 2020-10-29
  7. 2020/10/29 15:53:56 - 2020-10-29
  8. 2020/10/29 15:09:30 - 2020-10-29
  9. 2020/10/29 15:02:09 - 2020-10-29