For a while now I’ve been a bit annoyed at how limited the Twitch Kraken API is. It has a lot of nice features, sure, but it’s still missing a lot.

Twitch uses several old, undocumented APIs on their website. This is an attempt to provide a central post where I can explain what APIs are accessible and could be useful for someone else. I’ll also attempt to provide sample data where I can.

Other information may be available on the documentation for the Twitch API on GitHub, but this post will primarily cover what isn’t already documented in that repository.

Now before we start, I need to make something clear.

  • These API endpoints could disappear/be moved at any time without any updates regarding it whatsoever. I’m going to update this post every once in a while, but I would not 100% rely on either the endpoints or this post to be updated very frequently.
  • Some of these endpoints use the user ID instead of the username. The user ID can be found in most endpoints that give data of a specific user in any way, such as the /channels/ Kraken endpoint. In this case: user ID = _id
  • A lot of these endpoints aren’t loadable clientside due to CORS, even if authentication isn’t required.
  • There is a chance that these endpoints are rate-limited. Send your “client ID” in the header (as “Client-ID”) for every request if you wanna be on the safe side.

Custom parameters will always be placed in curly brackets (“{}”), and the URLs should always be prefixed with “https://api.twitch.tv/”. There are a few exceptions to this rule, but those exceptions will have the full URL. The hyperlinks the titles are set to, will most likely point to my own profile information or someone with a subscription program to show differences. Example data will also use my account/channel data unless something else is specified.

Endpoint index:

/api/channels/{CHANNEL_NAME}

Contains some information such as a profile’s Steam64 ID (if they have connected to Steam) and a few other IDs I’m not sure what is used for. Some might be for advertisements.

“product_path” seems to be the URL suffix (after twitch.tv) for a subscription program or similar.

Example data:

{
    "display_name": "Decicus",
    "game": "OpieOP",
    "status": "I'm Batman (ง ͠° ͟ل͜ ͡°)ง",
    "fight_ad_block": null,
    "_id": 25622621,
    "name": "decicus",
    "partner": false,
    "twitch_liverail_id": null,
    "liverail_id": null,
    "ppv": false,
    "comscore_id": null,
    "comscore_c6": null,
    "video_banner": null,
    "steam_id": "76561197997719567",
    "broadcaster_software": "unknown_rtmp",
    "prerolls": true,
    "postrolls": true,
    "product_path": ""
}

/api/channels/{CHANNEL_NAME}/ember

Shows some additional information such as the primary team “identifier” and the team’s display name (if they are in a team, that is).

It also contains a “chansub” value, which seems to be either “null” or a unique identifier of some sort.

The “creative” object can only be modified by partnered streamers.

Example data (Channel: Hirona):

{
    "mature": true,
    "status": "(• ◡•)/ Draw & hang before TwitchCon! #drawing #illustration #digitalillustration ",
    "broadcaster_language": "en",
    "display_name": "Hirona",
    "game": "Creative",
    "delay": 0,
    "_id": 39655944,
    "name": "hirona",
    "partner": true,
    "created_at": "2013-01-25T04:27:06Z",
    "updated_at": "2016-10-01T18:00:33Z",
    "teespring_campaign_enabled": false,
    "primary_team_name": "theblacklist",
    "primary_team_display_name": "The Blacklist",
    "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/hirona-profile_image-671abb8b2621450b-300x300.jpeg",
    "banner": null,
    "video_banner": "https://static-cdn.jtvnw.net/jtv_user_pictures/hirona-channel_offline_image-0b4cbd3d4d76ab56-640x360.jpeg",
    "background": null,
    "profile_banner": "https://static-cdn.jtvnw.net/jtv_user_pictures/hirona-profile_banner-8bf4bdb38270f64a-480.jpeg",
    "profile_banner_background_color": "#bdbdbd",
    "url": "https://www.twitch.tv/hirona",
    "views": 584442,
    "followers": 16840,
    "prerolls": true,
    "show_chat": true,
    "steam_id": null,
    "chansub": "afc07b03413f1a69932ce5b52119a74c",
    "creative": {
        "commission_button": true,
        "commission_text": "Hello! My commissions are currently *Closed*...",
        "commission_text_html": "Hello! My commissions are currently *Closed*..."
    }
}

Example data (Channel: Decicus):

{
    "mature": true,
    "status": "I'm Batman (ง ͠° ͟ل͜ ͡°)ง",
    "broadcaster_language": "en",
    "display_name": "Decicus",
    "game": "OpieOP",
    "delay": 0,
    "_id": 25622621,
    "name": "decicus",
    "partner": false,
    "created_at": "2011-10-22T13:38:29Z",
    "updated_at": "2016-01-14T18:37:44Z",
    "teespring_campaign_enabled": false,
    "primary_team_name": "theblacklist",
    "primary_team_display_name": "The Blacklist",
    "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/decicus-profile_image-f3a63ac915592989-300x300.jpeg",
    "banner": null,
    "video_banner": null,
    "background": null,
    "profile_banner": null,
    "profile_banner_background_color": null,
    "url": "http://www.twitch.tv/decicus",
    "views": 4246,
    "followers": 470,
    "prerolls": true,
    "show_chat": true,
    "chansub": null
}

/api/channels/{CHANNEL_NAME}/chat_properties

Contains information such as “subscriber-only chat”, if this chat is on the event servers instead of the normal chat servers and also the IPs/ports of the chat servers.

Also has some other information such as “require verified email to speak” or “hide chat links” – which is the built-in Twitch link filter (and, in my opinion, it’s pretty awful).

{
    "_id": 25622621,
    "hide_chat_links": false,
    "chat_delay_duration": 0,
    "chat_rules": ["- Use common sense", "- Ask for permission before posting links", "- Follow Twitch RoC and ToS like you should in any other channel as well."],
    "devchat": false,
    "game": "Portal 2",
    "require_verified_account": true,
    "subsonly": false,
    "chat_servers": ["irc.chat.twitch.tv:80", "irc.chat.twitch.tv:6667"],
    "web_socket_servers": ["irc-ws.chat.twitch.tv:80"],
    "web_socket_pct": 1.0,
    "darklaunch_pct": 1.0,
    "block_chat_notification_token": false,
    "available_chat_notification_tokens": [],
    "sce_title_preset_text_1": null,
    "sce_title_preset_text_2": null,
    "sce_title_preset_text_3": null,
    "sce_title_preset_text_4": null,
    "sce_title_preset_text_5": null
}

/api/playlists/channels/{USER_ID}

Contains information regarding a VOD playlist if it’s currently running. This uses the user ID instead of the channel name.

I haven’t really looked through a whole lot of the data for this but it seems to primarily contain what VOD is playing, how long it is and how much is left of it. As well as some information about what VODs are in the playlist.

There is another endpoint that seems to be identical to this, under: spectre.twitch.tv/v1/channels/{USER_ID}

Example data (Xangold’s channel):

{
    "id": 39141793,
    "enabled": true,
    "active_playlist_id": 345,
    "active": true,
    "playlists": [{
        "id": 345,
        "channel_id": 39141793,
        "playlist": {
            "vod_ids": [29632828, 23384166, 29830514]
        },
        "version": 1
    }],
    "playhead": {
        "active_vod_index": 2,
        "playlist_id": 345,
        "remaining_seconds_in_active_vod": 13678,
        "vods": [{
            "duration": 19049.966,
            "id": 29632828,
            "transition_segment": {
                "remaining_seconds": 32,
                "uris": {
                    "audio_only": "index-0000009509-Khmq-muted.ts",
                    "chunked": "index-0000009509-PCDT-muted.ts",
                    "high": "index-0000009509-4pyI-muted.ts",
                    "low": "index-0000009509-7NXZ-muted.ts",
                    "medium": "index-0000009509-TXqw-muted.ts",
                    "mobile": "index-0000009509-W2K6-muted.ts"
                }
            }
        }, {
            "duration": 18794,
            "id": 23384166,
            "transition_segment": {
                "remaining_seconds": 16,
                "uris": {
                    "audio_only": "index-0000009389-Atjs.ts",
                    "chunked": "index-0000009389-rXjk.ts",
                    "high": "index-0000009389-Rq9i.ts",
                    "low": "index-0000009389-cIF6.ts",
                    "medium": "index-0000009389-omJi.ts",
                    "mobile": "index-0000009389-qCMJ.ts"
                }
            }
        }, {
            "duration": 22396,
            "id": 29830514,
            "transition_segment": {
                "remaining_seconds": 18,
                "uris": {
                    "audio_only": "index-0000011189-Lp2k.ts",
                    "chunked": "index-0000011189-R8Op.ts",
                    "high": "index-0000011189-o7WG.ts",
                    "low": "index-0000011189-9fdu.ts",
                    "medium": "index-0000011189-AtZd.ts",
                    "mobile": "index-0000011189-23BG.ts"
                }
            }
        }]
    }
}

Example data (Channel: Decicus):

{
    "id": 25622621,
    "enabled": false,
    "active_playlist_id": -1,
    "active": false,
    "playlists": [],
    "playhead": null
}

/kraken/beta/streams/random

This one is technically part of the Kraken API, but it’s not documented on their GitHub.

If you didn’t notice from the URL, this will pull random streams from the directories. It’s the same endpoint that’s used under the “Random channels” directory on the main website.

It supports two GET parameters that I’m aware of: limit & offset. These parameters don’t seem to do anything, at least not “limit”, as they seem to provide 100 stream objects even if the limit parameter is set to something different. From my tests, “offset” doesn’t seem to affect anything either.

I will not provide example data for this endpoint, as the stream objects are identical to those provided in the normal /streams endpoint.

/api/channels/{CHANNEL_NAME}/product

This endpoint holds some information about a user’s subscription program, if they have one. It can be useful to use for checking if someone actually has a subscription program, because the Kraken API only gives information about partners (and you can be a Twitch partner without a subscription program).

It also contains some information about both “active” and “inactive” emotes. Where the “inactive” emotes are old, inaccessible (through Twitch chat) emotes. This endpoint seems to be used for the page whenever you want to subscribe to a channel, with displaying of subscription perks on the Twitch website itself.

Example data (xSmaK’s channel):

{
    "name": "xsmak",
    "product_url": "http://www.twitch.tv/products/xsmak",
    "html": "<p class=\"title\">Subscribe to <span class=\"prod\">xsmak</span>!</p>\n<br>\n\n<p class=\"message\">\nYour subscription will directly support the broadcaster and help advance the cause of professional gaming.\n</p>\n<br>\n\n<p class=\"message\">\nIt's currently only <span class=\"price\"> $4.99</span><span class=\"sub\">USD</span> per month.\n</p>\n<br>\n\n<img src=\"paywall.SubscriptionPurchaseButton\" id=\"purchase_button\" />",
    "css": "\np        {font-family: BestFont.HELVETICA;}\nli       {font-family: BestFont.HELVETICA; text-decoration: underline;}\n.title   {color: #FFF; font-size: 21pt;}\n.message {color: #CCC;font-size: 12pt;text-align: left;leading: 2.4pt;}\n.price   {font-size: 16pt;leading: 3.2pt;color:#EEE;}\n.prod    {color: #B4B9BF; font-weight: bold; }\n.sub     {font-size: 7pt;}\n.footer  {color: #DDD; font-size: 9.5pt;}\na        {color: #6441A5; font-family: BestFont.HELVETICA;\n          font-size: 12pt;\n          text-decoration: none;}\n.wait    {color: #FF2; font-size: 24;}\n.error   {color: #FF2; font-size: 12pt;}\nimg      {display: inline;}",
    "price": "$4.99",
    "emoticons": [{
        "id": 73538,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakAttack",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-73538-src-38ce189b0adc5508-28x28.png",
        "subscriber_only": true
    }, {
        "id": 73539,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakWD",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-73539-src-9fdf1cb032feff31-28x28.png",
        "subscriber_only": true
    }, {
        "id": 73540,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakTrain",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-73540-src-52471a1cc0a0a453-28x28.png",
        "subscriber_only": true
    }, {
        "id": 33655,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakN",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-33655-src-956c00c58290236d-28x28.png",
        "subscriber_only": true
    }, {
        "id": 33653,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakH",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-33653-src-043fc2d26f8ae840-28x28.png",
        "subscriber_only": true
    }, {
        "id": 33657,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakR",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-33657-src-3de9d139d12b2ac2-28x28.png",
        "subscriber_only": true
    }, {
        "id": 2088,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakRepresent",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/chansub-global-emoticon-0a794589d51866ba-28x28.png",
        "subscriber_only": true
    }, {
        "id": 5138,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakHatsoff",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-5138-src-37a3ffb5384465e3-28x28.png",
        "subscriber_only": true
    }, {
        "id": 16736,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakRoss",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-16736-src-288d564def33065b-28x28.png",
        "subscriber_only": true
    }, {
        "id": 27319,
        "width": 28,
        "height": 28,
        "state": "active",
        "regex": "smakM",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-27319-src-c23168e36b645253-28x28.png",
        "subscriber_only": true
    }, {
        "id": 33651,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakF",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-33651-src-98658e6b37ac13e8-28x28.png",
        "subscriber_only": true
    }, {
        "id": 33652,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakL",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-33652-src-5708e7bce54fe3d2-28x28.png",
        "subscriber_only": true
    }, {
        "id": 2087,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakHatsoff",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/chansub-global-emoticon-f6bb201b32e6f91b-28x28.png",
        "subscriber_only": true
    }, {
        "id": 16670,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakRoss",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-16670-src-3b1692e1613b7311-28x28.png",
        "subscriber_only": true
    }, {
        "id": 17890,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakTC",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-17890-src-f93ed4c3ada961a1-28x28.png",
        "subscriber_only": true
    }, {
        "id": 17881,
        "width": 28,
        "height": 28,
        "state": "inactive",
        "regex": "smakTC",
        "emoticon_set": 303,
        "url": "https://static-cdn.jtvnw.net/jtv_user_pictures/emoticon-17881-src-f510ea9714b6dead-28x28.png",
        "subscriber_only": true
    }]
}

 Example data (Channel: Decicus):

{
    "error": "Not Found",
    "status": 404,
    "message": "No subscription product exists"
}

/api/channels/{CHANNEL_NAME}/panels

This is used on every channel page and holds information about each panel on the channel, such as: ordering, what type (which currently seems to only be either “teespring” for Teespring t-shirt campaigns or “default” for the normal panels you edit via your channel page), the description in both HTML and Markdown format, as well as channel name and user ID. It also contains the image and image link as well as the panel title, if these are set.

The example data below will display two different formats. One is default, the other is a Teespring campaign (expired).

Example data (IwinUloseLOL’s channel):

[{
    "_id": 1391476,
    "display_order": 1,
    "kind": "default",
    "html_description": "<p>My name is Iwinz! or Joshua. Im 25 and from the west coast USA. I like to play and stream dayz/arma and other related games.. I also like film... c:\nMy name should probably be IloseUwinLOL because Im bad at games..  <a href=\"http://iwinuloselol.com/\">Iwinz Website!</a></p>\n",
    "user_id": 39861453,
    "data": {
        "link": "",
        "image": "http://static-cdn.jtvnw.net/jtv_user_pictures/panel-39861453-image-9c27874796896251-320.png",
        "title": "",
        "description": "My name is Iwinz! or Joshua. Im 25 and from the west coast USA. I like to play and stream dayz/arma and other related games.. I also like film... c: \nMy name should probably be IloseUwinLOL because Im bad at games..  [Iwinz Website!](http://iwinuloselol.com/)"
    },
    "channel": "iwinuloselol"
}, {
    "_id": 5259853,
    "display_order": 10,
    "kind": "teespring",
    "html_description": "At long last it is finally here! As requested the <i>iwinOmg</i> in all its 8bit glory! A limited edition one time offer. Thanks for all the support! <b>Much Lahv!</b><br>",
    "user_id": 39861453,
    "data": {
        "id": 8317,
        "user_id": 39861453,
        "name": "Iwinz OMG Heart! 8Bit",
        "description": "At long last it is finally here! As requested the <i>iwinOmg</i> in all its 8bit glory! A limited edition one time offer. Thanks for all the support! <b>Much Lahv!</b><br>",
        "start_date": "2015-05-06T14:54:41Z",
        "end_date": "2015-05-27T03:11:21Z",
        "image_front": "//images.teespring.com/shirt_pic/2285658/2438231/300/6151/front.png?v=2015-05-05-19-51",
        "image_back": "//images.teespring.com/shirt_pic/2285658/2438231/300/6151/back.png?v=2015-05-05-19-51",
        "colors": "--- \n- 6151\n",
        "reservations": 44,
        "tipping_point": 15,
        "campaign_url": "http://teespring.com/twitch/iwinz-omg-heart-8bit",
        "state": "success",
        "teespring_id": 2285658,
        "price": 2371,
        "created_at": "2015-05-05T19:51:14Z",
        "updated_at": "2015-05-27T03:12:18Z"
    },
    "channel": "iwinuloselol"
}]

/api/users/{CHANNEL_NAME}/followed/hosting

This endpoint is used on the /directory/following page on the main website and contains channels that are currently hosting someone, and who they’re hosting in that case.

The endpoint supports both “limit” and “offset” GET parameters, which behave identical to the parameters that are used with the /streams endpoint.

The example data below uses both limit (=5) and offset (=0, so it doesn’t affect it).

Example data (Channel: Decicus):

{
    "_links": {
        "self": "https://api.twitch.tv/api/users/decicus/followed/hosting?limit=5&offset=0",
        "next": "https://api.twitch.tv/api/users/decicus/followed/hosting?limit=5&offset=5"
    },
    "_total": 22,
    "hosts": [{
        "id": 16312051,
        "name": "iamsp00n",
        "target": {
            "id": "jonbams",
            "channel": {
                "id": 28252159,
                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/jonbams-profile_image-79389ec029fb0687-300x300.png",
                "url": "http://www.twitch.tv/jonbams",
                "display_name": "JonBams",
                "name": "jonbams"
            },
            "meta_game": "Minecraft",
            "preview": "https://static-cdn.jtvnw.net/previews-ttv/live_user_jonbams-320x180.jpg",
            "title": "BuildGuild | FTB Infinity EXPERT! | ",
            "url": "http://www.twitch.tv/jonbams",
            "viewers": 1566,
            "_id": 28252159
        },
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/iamsp00n-profile_image-64c6628d06afa743-300x300.png",
        "display_name": "IAmSp00n"
    }, {
        "id": 12984340,
        "name": "ms_vixen",
        "target": {
            "id": "edemonster",
            "channel": {
                "id": 23612492,
                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/edemonster-profile_image-1d3d6b58d6cdeba5-300x300.png",
                "url": "http://www.twitch.tv/edemonster",
                "display_name": "EdEMonster",
                "name": "edemonster"
            },
            "meta_game": "Tom Clancy's Rainbow Six: Siege",
            "preview": "https://static-cdn.jtvnw.net/previews-ttv/live_user_edemonster-320x180.jpg",
            "title": "[ENG] [PS4] ~ Thank YOU for 56k Follows!! <3",
            "url": "http://www.twitch.tv/edemonster",
            "viewers": 522,
            "_id": 23612492
        },
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/ms_vixen-profile_image-09d5742fc3f91597-300x300.jpeg",
        "display_name": "Ms_Vixen"
    }, {
        "id": 39114905,
        "name": "ohnoporkchop",
        "target": {
            "id": "aurora_peachy",
            "channel": {
                "id": 48395246,
                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/aurora_peachy-profile_image-d7bc8476dadf36ca-300x300.png",
                "url": "http://www.twitch.tv/aurora_peachy",
                "display_name": "Aurora_Peachy",
                "name": "aurora_peachy"
            },
            "meta_game": "Guild Wars 2",
            "preview": "https://static-cdn.jtvnw.net/previews-ttv/live_user_aurora_peachy-320x180.jpg",
            "title": "\u2665 Peachy Party: Adventures, Fun & Prizes! [EU] \u2665 !200",
            "url": "http://www.twitch.tv/aurora_peachy",
            "viewers": 215,
            "_id": 48395246
        },
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/ohnoporkchop-profile_image-21538329bdec0e0d-300x300.jpeg",
        "display_name": "OhNoPorkchop"
    }, {
        "id": 72322952,
        "name": "selvek",
        "target": {
            "id": "thatscat",
            "channel": {
                "id": 66470213,
                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/thatscat-profile_image-e176871d0df14d8e-300x300.jpeg",
                "url": "http://www.twitch.tv/thatscat",
                "display_name": "ThatsCat",
                "name": "thatscat"
            },
            "meta_game": "Beyond: Two Souls",
            "preview": "https://static-cdn.jtvnw.net/previews-ttv/live_user_thatscat-320x180.jpg",
            "title": "Beyond: Two Souls [Blind Playthrough]",
            "url": "http://www.twitch.tv/thatscat",
            "viewers": 187,
            "_id": 66470213
        },
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/selvek-profile_image-b1b9f22748990663-300x300.png",
        "display_name": "Selvek"
    }, {
        "id": 42218536,
        "name": "septicfalcon",
        "target": {
            "id": "dannyyplays",
            "channel": {
                "id": 51743718,
                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/dannyyplays-profile_image-2a042d520a451ae8-300x300.png",
                "url": "http://www.twitch.tv/dannyyplays",
                "display_name": "DannyyPlays",
                "name": "dannyyplays"
            },
            "meta_game": "DayZ",
            "preview": "https://static-cdn.jtvnw.net/previews-ttv/live_user_dannyyplays-320x180.jpg",
            "title": "Contemplating life with a loaded SVD - @Dannyyplays",
            "url": "http://www.twitch.tv/dannyyplays",
            "viewers": 130,
            "_id": 51743718
        },
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/septicfalcon-profile_image-c4437b455423015c-300x300.jpeg",
        "display_name": "SepticFalcon"
    }]
}

/api/cs/maps

This is used for the “map picker” at the top of the page for the Counter-Strike: Global Offensive game directory on Twitch. It doesn’t contain much other than map name and viewer counts for each map.

Example data:

{
    "_total": 18,
    "maps": [{
        "map": "de_mirage",
        "map_name": "Mirage",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/882984447753219894/D947D4FA6CC0CA4D3DE8D67D8B40A3EFC462EE19/200x112.resizedimage",
        "viewers": 8423
    }, {
        "map": "de_dust2",
        "map_name": "Dust II",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/884099387636144833/64CCC9FAC3B2294B270D7F566478E9AE363DD445/200x112.resizedimage",
        "viewers": 7330
    }, {
        "map": "custom",
        "map_name": "Custom",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/884099481706885047/886D654F4A4ED3BFCD60B07DBA6BB4625D466B52/200x112.resizedimage",
        "viewers": 6672
    }, {
        "map": "de_train",
        "map_name": "Train",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/550893892999129894/9DFDA48BA22BDBD7ABFDE5AD82E09E28AFB64C2B/200x112.resizedimage",
        "viewers": 2967
    }, {
        "map": "de_cache",
        "map_name": "Cache",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/921273757974084165/4B11951A0CF99376C092E1F80C00DE719346783A/200x112.resizedimage",
        "viewers": 1526
    }, {
        "map": "de_inferno",
        "map_name": "Inferno",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/884099387636152068/745C3B9DB3D39D69283BA75045BA175A150211A6/200x112.resizedimage",
        "viewers": 1282
    }, {
        "map": "de_cbble",
        "map_name": "Cobblestone",
        "map_img": "http://cloud-2.steamusercontent.com/ugc/666829239974957588/C390A1BB5CDFFDC7793B98143EB1177ACE38EC91/200x112.resizedimage",
        "viewers": 162
    }, {
        "map": "de_overpass",
        "map_name": "Overpass",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/666829239975015371/4690D66902FABBC0C9A155217BDF09197D3068D7/200x112.resizedimage",
        "viewers": 99
    }, {
        "map": "de_nuke",
        "map_name": "Nuke",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/884099387636154888/390DAE2D78345C553F5F667D06D66962B79557FF/200x112.resizedimage",
        "viewers": 60
    }, {
        "map": "ar_shoots",
        "map_name": "Shoots",
        "map_img": "http://cloud-2.steamusercontent.com/ugc/884099387636169843/FE8BD2809B9626E14CADF1940EF476A6785A9D3B/200x112.resizedimage",
        "viewers": 17
    }, {
        "map": "de_vertigo",
        "map_name": "Vertigo",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/884099387635965511/EBD899AB318941BBF572E7529F6404FFE88FEDDD/200x112.resizedimage",
        "viewers": 12
    }, {
        "map": "de_dust",
        "map_name": "Dust",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/884099387636142158/952C5F54CE8C1836C4775EEC6A3D4581AC96F83E/200x112.resizedimage",
        "viewers": 8
    }, {
        "map": "cs_office",
        "map_name": "Office",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/884099387636313020/C3724AB6908CA9DD37365B2391209AAF1951566D/200x112.resizedimage",
        "viewers": 8
    }, {
        "map": "de_lake",
        "map_name": "Lake",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/884099387636183928/C383E8A0FAA1A3F1BB01C09DA7B2BBE80D4A00A6/200x112.resizedimage",
        "viewers": 6
    }, {
        "map": "de_aztec",
        "map_name": "Aztec",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/884099387636138080/CB1B4067D1E87B7D2A13096912EE0F8F89907273/200x112.resizedimage",
        "viewers": 5
    }, {
        "map": "de_season",
        "map_name": "Season",
        "map_img": "http://cloud-4.steamusercontent.com/ugc/540754449043789761/A64321A504CE32D0F492D5D6F1364C9044666BAB/200x112.resizedimage",
        "viewers": 4
    }, {
        "map": "cs_italy",
        "map_name": "Italy",
        "map_img": "http://cloud-2.steamusercontent.com/ugc/884099481704487049/47425465FBEF230EA597F260AE32AE7F0AA0F6A3/200x112.resizedimage",
        "viewers": 2
    }, {
        "map": "ar_monastery",
        "map_name": "Monastery",
        "map_img": "http://cloud-2.steamusercontent.com/ugc/884099387635990260/AAFA36A78AA984736E0C1996AD0B6B5D4F3E4B9D/200x112.resizedimage",
        "viewers": 1
    }]
}

/api/cs

This is basically a “streams” endpoint for Counter-Strike: Global Offensive, but contains extra information (other than the information that you can find in the normal /streams endpoints), such as: skill, map, map name & map image.

Keep in mind, those entries may be either a blank string or simply NULL.

This endpoint also supports “limit” and “offset” GET parameters.

Example data (limit=2 & offset=50):

{
    "_total": 1880,
    "_links": {
        "self": "https://api.twitch.tv/api/cs?limit=2&offset=50",
        "next": "https://api.twitch.tv/api/cs?limit=2&offset=52",
        "prev": "https://api.twitch.tv/api/cs?limit=2&offset=48"
    },
    "streams": [{
        "_id": 19007082160,
        "game": "Counter-Strike: Global Offensive",
        "viewers": 314,
        "map": "de_mirage",
        "map_name": "Mirage",
        "map_img": "http://cloud-3.steamusercontent.com/ugc/882984447753219894/D947D4FA6CC0CA4D3DE8D67D8B40A3EFC462EE19/200x112.resizedimage",
        "skill": 17,
        "preview": {
            "small": "https://static-cdn.jtvnw.net/previews-ttv/live_user_schubii93-80x45.jpg",
            "medium": "https://static-cdn.jtvnw.net/previews-ttv/live_user_schubii93-320x180.jpg",
            "large": "https://static-cdn.jtvnw.net/previews-ttv/live_user_schubii93-640x360.jpg",
            "template": "https://static-cdn.jtvnw.net/previews-ttv/live_user_schubii93-{width}x{height}.jpg"
        },
        "is_playlist": false,
        "_links": {
            "self": "https://api.twitch.tv/kraken/streams/schubii93"
        },
        "user": {
            "mature": false,
            "status": "[german/english] r0myJB. - f*ck it, i cant fix my sound. Deal with it or die.",
            "broadcaster_language": "de",
            "display_name": "Schubii93",
            "game": "Counter-Strike: Global Offensive",
            "_id": 30918616,
            "name": "schubii93",
            "bio": "r0my",
            "partner": false,
            "created_at": "2012-05-30T17:36:00Z",
            "updated_at": "2016-01-19T19:15:55Z",
            "delay": null,
            "prerolls": true,
            "postrolls": true,
            "primary_team_name": null,
            "primary_team_display_name": null,
            "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/schubii93-profile_image-4cd5584c1f40b311-300x300.png",
            "banner": null,
            "video_banner": null,
            "background": null,
            "profile_banner": "https://static-cdn.jtvnw.net/jtv_user_pictures/schubii93-profile_banner-2f9b511e6290c285-480.jpeg",
            "profile_banner_background_color": "#000000",
            "url": "http://www.twitch.tv/schubii93",
            "views": 24282,
            "followers": 1994
        }
    }, {
        "_id": 19007363824,
        "game": "Counter-Strike: Global Offensive",
        "viewers": 312,
        "map": null,
        "map_name": null,
        "map_img": null,
        "skill": null,
        "preview": {
            "small": "https://static-cdn.jtvnw.net/previews-ttv/live_user_reruntv-80x45.jpg",
            "medium": "https://static-cdn.jtvnw.net/previews-ttv/live_user_reruntv-320x180.jpg",
            "large": "https://static-cdn.jtvnw.net/previews-ttv/live_user_reruntv-640x360.jpg",
            "template": "https://static-cdn.jtvnw.net/previews-ttv/live_user_reruntv-{width}x{height}.jpg"
        },
        "is_playlist": false,
        "_links": {
            "self": "https://api.twitch.tv/kraken/streams/reruntv"
        },
        "user": {
            "mature": null,
            "status": "Titan vs QuestionMark - SL i-League StarSeries XIV Finals - map1",
            "broadcaster_language": "en",
            "display_name": "RerunTV",
            "game": "Counter-Strike: Global Offensive",
            "_id": 96400744,
            "name": "reruntv",
            "bio": null,
            "partner": false,
            "created_at": "2015-07-17T18:26:42Z",
            "updated_at": "2016-01-19T19:21:14Z",
            "delay": null,
            "prerolls": true,
            "postrolls": true,
            "primary_team_name": null,
            "primary_team_display_name": null,
            "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/reruntv-profile_image-338018d90f1a70ed-300x300.jpeg",
            "banner": null,
            "video_banner": null,
            "background": null,
            "profile_banner": null,
            "profile_banner_background_color": null,
            "url": "http://www.twitch.tv/reruntv",
            "views": 19080,
            "followers": 1261
        }
    }]
}

/api/creative/tags

Essentially just a list of “tags” used in the Creative directory on Twitch.

/api/channels/{CHANNEL_NAME}/panels/custom_panel?stubbed=true

This is possibly the weirdest API endpoint I’ve found through Twitch. Not only does the channel name not matter at all, you have to include the “stubbed=true” GET parameter in the URL for it to even return anything other than NULL.

I won’t include any example data for this, as it seems to include quite the amount of data and I’m not sure what this is even used for, other than information regarding the game League of Legends.

/api/users/{CHANNEL_NAME}/follows/games

Returns some information about the games a user follows. This also supports limit and offset GET parameters.

Example data (Channel: Decicus – limit=1 & offset=1):

{
    "_total": 5,
    "follows": [{
        "name": "DayZ",
        "_id": 65632,
        "giantbomb_id": 39256,
        "box": {
            "large": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-272x380.jpg",
            "medium": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-136x190.jpg",
            "small": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-52x72.jpg",
            "template": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-{width}x{height}.jpg"
        },
        "logo": {
            "large": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-240x144.jpg",
            "medium": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-120x72.jpg",
            "small": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-60x36.jpg",
            "template": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-{width}x{height}.jpg"
        },
        "properties": {},
        "_links": {}
    }]
}

/api/users/{CHANNEL_NAME}/follows/games/live

Somewhat identical to the /follows/games one, except this also returns viewer count and how many channels are live in each game category. Like the previous endpoint, it supports limit and offset GET parameters.

Example data (My channel: Decicus – limit=1 & offset=1):

{
    "_total": 5,
    "follows": [{
        "viewers": 7911,
        "channels": 136,
        "game": {
            "name": "DayZ",
            "_id": 65632,
            "giantbomb_id": 39256,
            "box": {
                "large": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-272x380.jpg",
                "medium": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-136x190.jpg",
                "small": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-52x72.jpg",
                "template": "http://static-cdn.jtvnw.net/ttv-boxart/DayZ-{width}x{height}.jpg"
            },
            "logo": {
                "large": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-240x144.jpg",
                "medium": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-120x72.jpg",
                "small": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-60x36.jpg",
                "template": "http://static-cdn.jtvnw.net/ttv-logoart/DayZ-{width}x{height}.jpg"
            },
            "properties": {},
            "_links": {}
        }
    }]
}

/api/users/{CHANNEL_NAME}/follows/games/isFollowing?name={GAME_NAME}

Works somewhat similarly to the “followed games” endpoint. Although, this one requires you to specify the game name and will return either information about the game (if the user is following) or an error saying the user isn’t following. Keep in mind, in the error, the user is referred to by their user ID and the game by their “game ID”.

Both examples below are from my channel.

Example data (A game I follow: Counter-Strike: Global Offensive):

{
    "name": "Counter-Strike: Global Offensive",
    "popularity": 1222,
    "_id": 32399,
    "giantbomb_id": 36113,
    "box": {
        "large": "http://static-cdn.jtvnw.net/ttv-boxart/Counter-Strike:%20Global%20Offensive-272x380.jpg",
        "medium": "http://static-cdn.jtvnw.net/ttv-boxart/Counter-Strike:%20Global%20Offensive-136x190.jpg",
        "small": "http://static-cdn.jtvnw.net/ttv-boxart/Counter-Strike:%20Global%20Offensive-52x72.jpg",
        "template": "http://static-cdn.jtvnw.net/ttv-boxart/Counter-Strike:%20Global%20Offensive-{width}x{height}.jpg"
    },
    "logo": {
        "large": "http://static-cdn.jtvnw.net/ttv-logoart/Counter-Strike:%20Global%20Offensive-240x144.jpg",
        "medium": "http://static-cdn.jtvnw.net/ttv-logoart/Counter-Strike:%20Global%20Offensive-120x72.jpg",
        "small": "http://static-cdn.jtvnw.net/ttv-logoart/Counter-Strike:%20Global%20Offensive-60x36.jpg",
        "template": "http://static-cdn.jtvnw.net/ttv-logoart/Counter-Strike:%20Global%20Offensive-{width}x{height}.jpg"
    },
    "properties": {},
    "_links": {}
}

 Example data (A game I don’t follow: Twitch Plays):

{
    "error": "Not Found",
    "status": 404,
    "message": "25622621 isn't following 491180"
}

/api/friendships/users?ids={USER_IDS}

This one is quite interesting, because I can’t figure out what it’s technically used for. The parameter ids supports a comma-separated list of user IDs, and will return information about said user IDs. I could see it being useful if you want to store users by their unique user IDs instead of the channel names. This could be used as a way to reverse lookup the username of the user using said user ID.

The sorting of the data seems to be sequential following the user IDs.

Example data (My account + Xangold):

{
    "users": [{
        "id": 25622621,
        "display_name": "Decicus",
        "login": "decicus",
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/decicus-profile_image-f3a63ac915592989-70x70.jpeg"
    }, {
        "id": 39141793,
        "display_name": "Xangold",
        "login": "xangold",
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/xangold-profile_image-ddf7eb43c851ad2a-70x70.jpeg"
    }]
}

/api/team/{TEAM_ID}/all_channels.json

Update 2016-04-15: This has been removed – See this reply on the Twitch developer forums

This returns a list of channels in a team, with some information about each channel. This seems to be the only way to retrieve a team’s channels. Live channels are listed at the top, then I’m unsure about how the sorting goes afterwards.

The “TEAM_ID” is the identifier for the team. This can be found in the URL when you visit’s a team page, and is the “name” after twitch.tv/team/

The example only includes one channel, as the information is pretty much identical for each channel. The status can be either “live” or “offline”.

Note: I’ve had some issues in the past with this endpoint redirecting to an invalid page over HTTPS. If this occurs for you, using HTTP should work.

Example data (One channel):

{
    "channels": [{
        "channel": {
            "name": "xsmak",
            "description": "Welcome! My name is Austin and I am a gamer and full time streamer from America. I will be playing games that satisfy my needs for an adversarial challenge. Don't be afraid to speak up in chat, I love interacting with viewers as much as possible. Don't forget to follow if you enjoy!",
            "title": "DayZ then Siege!",
            "meta_game": "DayZ",
            "display_name": "xSmaK",
            "link": "https://twitch.tv/xsmak",
            "image": {
                "size600": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-600x600.png",
                "size300": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-300x300.png",
                "size150": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-150x150.png",
                "size70": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-70x70.png",
                "size50": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-50x50.png",
                "size28": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-59b83bdb901ebc57-28x28.png"
            },
            "status": "live",
            "followers_count": 94409,
            "total_views": 3648625,
            "current_viewers": 326
        }
    }]
}

/api/team/{TEAM_ID}/live_channels.json

Works identical to the previous team endpoint, except this one lists only live channels.

tmi.twitch.tv/hosts?include_logins=1&target={USER_ID}

Has information about users who is hosting the “target”. For each object, there is the host_id, which is the user ID of the one hosting and the target ID, which is identical to the one specified in the “target” parameter. The GET parameter “include_logins” can be removed (or set to “0”) to not display the usernames/display names of the ones hosting or the one being hosted.

Example data (EpicFuel’s channel):

{
    "hosts": [{
        "host_id": 58141105,
        "target_id": 21281491,
        "host_login": "its_reds",
        "target_login": "epicfuel",
        "host_display_name": "Its_reds",
        "target_display_name": "EpicFuel"
    }, {
        "host_id": 25622621,
        "target_id": 21281491,
        "host_login": "decicus",
        "target_login": "epicfuel",
        "host_display_name": "Decicus",
        "target_display_name": "EpicFuel"
    }, {
        "host_id": 74808402,
        "target_id": 21281491,
        "host_login": "klumaak1",
        "target_login": "epicfuel",
        "host_display_name": "KlumaAK1",
        "target_display_name": "EpicFuel"
    }]
}

tmi.twitch.tv/hosts?include_logins=1&host={USER_ID}

Holds information about who a channel is hosting, if they’re hosting someone.

If they’re not hosting someone, only “host_id” and “host_login” will be included in the response. “host_login” is excluded if include_logins is 0.

Example data (Channel: Decicus – Hosting: Sterbefall):

{
    "hosts": [{
        "host_id": 25622621,
        "target_id": 41568722,
        "host_login": "decicus",
        "target_login": "sterbefall"
    }]
}

badges.twitch.tv/v1/badges/global/display – Added on 2016-06-03

Holds information about chat badges across Twitch. Supports a “language” URL parameter, which seems to use an ISO 693-1 code, but as of date of adding, does not affect the data returned.

Link to discussion on Twitch developer forums

Example data – This was fetched during the Warcraft movie promotion.

{
  "badge_sets": {
    "admin": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/9ef7e029-4cdf-4d4d-a0d5-e2b3fb2583fe/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/9ef7e029-4cdf-4d4d-a0d5-e2b3fb2583fe/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/9ef7e029-4cdf-4d4d-a0d5-e2b3fb2583fe/3",
          "description": "Twitch Admin",
          "title": "Twitch Admin",
          "click_action": "none",
          "click_url": ""
        }
      }
    },
    "bits": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/73b5c3fb-24f9-4a82-a852-2f475b59411c/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/73b5c3fb-24f9-4a82-a852-2f475b59411c/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/73b5c3fb-24f9-4a82-a852-2f475b59411c/3",
          "description": " ",
          "title": "cheer1",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        },
        "100": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/09d93036-e7ce-431c-9a9e-7044297133f2/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/09d93036-e7ce-431c-9a9e-7044297133f2/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/09d93036-e7ce-431c-9a9e-7044297133f2/3",
          "description": " ",
          "title": "cheer100",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        },
        "1000": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/0d85a29e-79ad-4c63-a285-3acd2c66f2ba/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/0d85a29e-79ad-4c63-a285-3acd2c66f2ba/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/0d85a29e-79ad-4c63-a285-3acd2c66f2ba/3",
          "description": " ",
          "title": "cheer1000",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        },
        "10000": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/68af213b-a771-4124-b6e3-9bb6d98aa732/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/68af213b-a771-4124-b6e3-9bb6d98aa732/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/68af213b-a771-4124-b6e3-9bb6d98aa732/3",
          "description": " ",
          "title": "cheer10000",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        },
        "100000": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/96f0540f-aa63-49e1-a8b3-259ece3bd098/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/96f0540f-aa63-49e1-a8b3-259ece3bd098/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/96f0540f-aa63-49e1-a8b3-259ece3bd098/3",
          "description": " ",
          "title": "cheer100000",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        },
        "5000": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/57cd97fc-3e9e-4c6d-9d41-60147137234e/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/57cd97fc-3e9e-4c6d-9d41-60147137234e/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/57cd97fc-3e9e-4c6d-9d41-60147137234e/3",
          "description": " ",
          "title": "cheer5000",
          "click_action": "visit_url",
          "click_url": "https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"
        }
      }
    },
    "broadcaster": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/5527c58c-fb7d-422d-b71b-f309dcb85cc1/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/5527c58c-fb7d-422d-b71b-f309dcb85cc1/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/5527c58c-fb7d-422d-b71b-f309dcb85cc1/3",
          "description": "Broadcaster",
          "title": "Broadcaster",
          "click_action": "none",
          "click_url": ""
        }
      }
    },
    "global_mod": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/9384c43e-4ce7-4e94-b2a1-b93656896eba/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/9384c43e-4ce7-4e94-b2a1-b93656896eba/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/9384c43e-4ce7-4e94-b2a1-b93656896eba/3",
          "description": "Global Moderator",
          "title": "Global Moderator",
          "click_action": "none",
          "click_url": ""
        }
      }
    },
    "moderator": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-4b17-b3df-f923a41db1d0/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-4b17-b3df-f923a41db1d0/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-4b17-b3df-f923a41db1d0/3",
          "description": "Moderator",
          "title": "Moderator",
          "click_action": "none",
          "click_url": ""
        }
      }
    },
    "premium": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/a1dd5073-19c3-4911-8cb4-c464a7bc1510/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/a1dd5073-19c3-4911-8cb4-c464a7bc1510/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/a1dd5073-19c3-4911-8cb4-c464a7bc1510/3",
          "description": "Twitch Prime",
          "title": "Twitch Prime",
          "click_action": "visit_url",
          "click_url": "https://twitch.amazon.com/prime"
        }
      }
    },
    "staff": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/d97c37bd-a6f5-4c38-8f57-4e4bef88af34/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/d97c37bd-a6f5-4c38-8f57-4e4bef88af34/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/d97c37bd-a6f5-4c38-8f57-4e4bef88af34/3",
          "description": "Twitch Staff",
          "title": "Twitch Staff",
          "click_action": "none",
          "click_url": ""
        }
      }
    },
    "subscriber": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/19dd8673-124d-4f44-830c-b0f4f9d78635/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/19dd8673-124d-4f44-830c-b0f4f9d78635/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/19dd8673-124d-4f44-830c-b0f4f9d78635/3",
          "description": "Subscriber",
          "title": "Subscriber",
          "click_action": "subscribe_to_channel",
          "click_url": ""
        }
      }
    },
    "turbo": {
      "versions": {
        "1": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/bd444ec6-8f34-4bf9-91f4-af1e3428d80f/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/bd444ec6-8f34-4bf9-91f4-af1e3428d80f/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/bd444ec6-8f34-4bf9-91f4-af1e3428d80f/3",
          "description": "Turbo",
          "title": "Turbo",
          "click_action": "turbo",
          "click_url": ""
        }
      }
    },
    "warcraft": {
      "versions": {
        "alliance": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/c4816339-bad4-4645-ae69-d1ab2076a6b0/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/c4816339-bad4-4645-ae69-d1ab2076a6b0/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/c4816339-bad4-4645-ae69-d1ab2076a6b0/3",
          "description": "For Lordaeron!",
          "title": "Alliance",
          "click_action": "visit_url",
          "click_url": "http://warcraftontwitch.tv/"
        },
        "horde": {
          "image_url_1x": "https://static-cdn.jtvnw.net/badges/v1/de8b26b6-fd28-4e6c-bc89-3d597343800d/1",
          "image_url_2x": "https://static-cdn.jtvnw.net/badges/v1/de8b26b6-fd28-4e6c-bc89-3d597343800d/2",
          "image_url_4x": "https://static-cdn.jtvnw.net/badges/v1/de8b26b6-fd28-4e6c-bc89-3d597343800d/3",
          "description": "For the Horde!",
          "title": "Horde",
          "click_action": "visit_url",
          "click_url": "http://warcraftontwitch.tv/"
        }
      }
    }
  }
}

badges.twitch.tv/v1/badges/channels/{USER_ID}/display – Added on 2016-06-03

Aimed towards specific channels. As of right now, it only really displays anything if you have a custom subscriber badge. This also seems to ‘support’ a “language” parameter like the global endpoint does, but this doesn’t change the behavior of the result data.

Link to discussion on Twitch developer forums

Example data – Xangold’s channel

{
    "badge_sets": {
        "subscriber": {
            "versions": {
                "1": {
                    "image_url_1x": "https://static-cdn.jtvnw.net/jtv_user_pictures/badges/15029/18x18.png",
                    "image_url_2x": "https://static-cdn.jtvnw.net/jtv_user_pictures/badges/15029/36x36.png",
                    "image_url_3x": "https://static-cdn.jtvnw.net/jtv_user_pictures/badges/15029/72x72.png",
                    "description": "Subscriber",
                    "title": "Subscriber",
                    "click_action": "subscribe_to_channel",
                    "click_url": ""
                }
            }
        }
    }
}

badge_sets is just an empty object for channels without a custom subscriber badge (as of right now)

tmi.twitch.tv/api/rooms/{USER_ID}/recent_messages

Contains an array of raw IRC messages that is the “chat history”.

Example data – My (Decicus) channel

{
    "messages": [
        "@badges=broadcaster/1,turbo/1;color=#1FE026;display-name=Decicus;emotes=;historical=1;id=cf099c33-28cc-414f-854d-e324adcc46b6;mod=1;room-id=25622621;subscriber=0;tmi-sent-ts=1475351499539;turbo=1;user-id=25622621;user-type=mod :decicus!decicus@decicus.tmi.twitch.tv PRIVMSG #decicus :test 1",
        "@badges=broadcaster/1,turbo/1;color=#1FE026;display-name=Decicus;emotes=;historical=1;id=217c9051-1c13-4902-a62b-fb0d77c26872;mod=1;room-id=25622621;subscriber=0;tmi-sent-ts=1475351500330;turbo=1;user-id=25622621;user-type=mod :decicus!decicus@decicus.tmi.twitch.tv PRIVMSG #decicus :test 2",
        "@badges=broadcaster/1,turbo/1;color=#1FE026;display-name=Decicus;emotes=;historical=1;id=c9651468-57a2-4e4a-ba0f-f1c256bfc3e8;mod=1;room-id=25622621;subscriber=0;tmi-sent-ts=1475351502146;turbo=1;user-id=25622621;user-type=mod :decicus!decicus@decicus.tmi.twitch.tv PRIVMSG #decicus :test 3",
        "@badges=moderator/1,turbo/1;color=#191970;display-name=Nightbot;emotes=;historical=1;id=e96706c7-2c1d-4a06-978b-e26d962d9cf3;mod=1;room-id=25622621;subscriber=0;tmi-sent-ts=1475351530064;turbo=1;user-id=19264788;user-type=mod :nightbot!nightbot@nightbot.tmi.twitch.tv PRIVMSG #decicus :test 4",
        "@badges=;color=#008000;display-name=Cac7us;emotes=;historical=1;id=bad77355-4a93-4d0d-83aa-44d4347c453f;mod=0;room-id=25622621;sent-ts=1475351576881;subscriber=0;tmi-sent-ts=1475351577985;turbo=0;user-id=75037666;user-type= :cac7us!cac7us@cac7us.tmi.twitch.tv PRIVMSG #decicus :test 5"
    ]
}

Thanks to freaktechnik on the /r/Twitch Discord for linking me this endpoint.

tmi.twitch.tv/group/user/{USERNAME}/chatters

Shows a list of users connected (while logged in) to chat.

Example data – My (Decicus) channel

{
    "_links": {},
    "chatter_count": 9,
    "chatters": {
        "moderators": [
            "cherrylynnie",
            "decicus",
            "fess_unreal",
            "phantom"
        ],
        "staff": [],
        "admins": [],
        "global_mods": [],
        "viewers": [
            "cac7us",
            "logviewer",
            "mattisony",
            "muxybot",
            "sterbefall"
        ]
    }
}

clips.twitch.tv/api/v1/clips/{CLIP_CHANNEL}/{CLIP_SLUG}

Shows some information about a Twitch clip.

Example data – Clip from xSmaK’s channel.

{
    "broadcaster_channel_url": "https://www.twitch.tv/xsmak",
    "broadcaster_display_name": "xSmaK",
    "broadcaster_id": "30782393",
    "broadcaster_login": "xsmak",
    "broadcaster_logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/xsmak-profile_image-82720245be72599b-300x300.png",
    "curator_channel_url": "https://www.twitch.tv/jakinthebox00",
    "curator_display_name": "jakinthebox00",
    "curator_id": "56502452",
    "curator_login": "jakinthebox00",
    "curator_logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/jakinthebox00-profile_image-dbbc8afc9a19393a-300x300.png",
    "preview_image": "https://clips-media-assets.twitch.tv/23291256144-offset-10316-preview.jpg",
    "thumbnails": {
        "medium": "https://clips-media-assets.twitch.tv/23291256144-offset-10316-preview-480x272.jpg",
        "small": "https://clips-media-assets.twitch.tv/23291256144-offset-10316-preview-260x147.jpg",
        "tiny": "https://clips-media-assets.twitch.tv/23291256144-offset-10316-preview-86x45.jpg"
    },
    "game": "DayZ",
    "created_at": "2016-09-29T21:29:22Z",
    "title": "Last cast before Twitchcon!",
    "clip_url": "https://clips.twitch.tv/xsmak/UglyElephantFailFish",
    "clip_status_url": "https://clips.twitch.tv/api/v1/clips/xsmak/UglyElephantFailFish/status",
    "vod_id": "92074525",
    "vod_url": "https://www.twitch.tv/xsmak/v/92074525?t=2h51m56s",
    "embed_url": "https://clips.twitch.tv/embed?clip=xsmak/UglyElephantFailFish",
    "embed_html": "-snip-",
    "view_url": "https://clips.twitch.tv/api/v1/clips/xsmak/UglyElephantFailFish/view",
    "id": "xsmak/UglyElephantFailFish",
    "slug": "UglyElephantFailFish",
    "duration": 29.204,
    "views": 34
}

End notes:

I hope that you get some use of this post. If you’d like to provide any feedback, you can contact me via the following methods:

  • E-mail: alex@thomassen.xyz
  • Twitter: @Decicus
  • Twitch: Decicus
  • Discord: Decicus#0001
  • You could also post a comment below this post, but they aren’t checked as often as the other contact points.

Special thanks to Mellow, Glyciant & Frog for helping me proofread and adjust the post before publishing. 

Twitch API – “Hidden” Endpoints
Tagged on: