Get information about streams on Twitch with PowerShell

Fri, May 10, 2019

Read in 4 minutes

PowerShell, the Twitch API and a sprinkle of magic, and a PowerShell function to get information about streams are born.

Get information about streams on Twitch with PowerShell

Introduction

I love watching streams on Twitch, especially matches in Counter-Strike Global Offensive (CS:GO). One time, when I was waiting for a game to start, and I got a little bored, I wondered how difficult it would be to query Twitch for stream information using PowerShell.

It turns out it’s not too bad at all!

But it doesn’t just work

PS C:\> Invoke-RestMethod -Uri 'https://api.twitch.tv/helix/streams'
Invoke-RestMethod : {"error":"Unauthorized","status":401,"message":"Must provide a valid Client-ID or OAuth token"}
At line:1 char:1
+ Invoke-RestMethod -Uri 'https://api.twitch.tv/helix/streams'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

It looks like I can’t just directly query the API, I need some authorization. Let’s see how that’s done.

Setting up Twitch access

First things first, I need an account on Twitch. I already have that, so far so good.

Next step is to sign up on https://dev.twitch.tv/ and get a key to access their API. Login is just my Twitch account, which I’ll then be asked to link to their development site.

Sign up with twitch dev
Login with twitch
Authorize development site

I then need to generate an API key, which I can do in the dashboard by registering a new application.

Go to dashboard
Register application

The name needs to be unique across all of Twitch. The OAuth Redirect URL is for more advanced scenarios, for example, if I want to authenticate my users through Twitch. It’s not relevant here, and localhost is fine. There are multiple options in Category, and I think Application Integration fits what I’m doing best.

Creating application

Now that the application is registered, I need to hit Manage to go back and see my Client ID.

Manage application
Manage application

Using PowerShell to get info from Twitch

Now I have access to Twitch’s API, then what? First I’ll check that I can query the Twitch API. Scanning through the documentation, I can see they have an example for getting streams. Even though it says “None” in Authentication, I need to pass my client ID in the header for every request. Here goes:

$headers = @{ 'client-id'='ClientIdFromDevTwitch' }
$result = Invoke-RestMethod -Uri 'https://api.twitch.tv/helix/streams' -Headers $headers

PS C:\> $result.data.Count
20

PS C:\> $result.data[0]

id            : 34070510592
user_id       : 36029255
user_name     : Riot Games
game_id       : 21779
community_ids : {ad14d4fc-1a7c-413f-aa32-4906ef3669ae}
type          : live
title         : MSI Groups Day 2: Team Liquid vs. Invictus Gaming
viewer_count  : 98403
started_at    : 2019-05-11T05:30:02Z
language      : en
thumbnail_url : https://static-cdn.jtvnw.net/previews-ttv/live_user_riotgames-{width}x{height}.jpg
tag_ids       : {6ea6bca4-4712-4ab9-a906-e3336a9d8039}

Great, I’m getting data! But, only 20 streams returned for all Twitch streams? Turns out they won’t return more than 20 streams by default, and max 100. But there’s a trick, because I get a “cursor” with each response that I can use to get the next 20 (or 100) results for my query.

PS C:\> $result.pagination

cursor
------
eyJiIjpudWxsLCJhIjp7Ik9mZnNldCI6MjB9fQ

I’ll limit my query to only CS:GO streams in English and then try to iterate through them all.

$headers = @{"client-id" = 'ClientIdFromDevTwitch'}

$result = $null
$streams = @()

do {
    $cursor = ""

    if ($result) { 
        $cursor = $result.pagination.cursor
    }

    $uri = "https://api.twitch.tv/helix/streams?game_id=32399&first=100&language=en&after={0}" -f $cursor
    $result = Invoke-RestMethod -Method Get -Headers $headers -Uri $uri
    $streams += $result.data

    Write-Host "$($result.data.Count) streams found in page"
} while ($result.data.Count -eq 100)

100 streams found in page
100 streams found in page
46 streams found in page

PS C:\> $streams.Count
246

The script works like a charm. In the $uri variable, I added a few query parameters, where ‘game_id’ is the specific game, and I happen to know that CS:GO is 32399. Then I’m using ‘first’ with a value of 100, which increases the results returned to 100, the maximum supported by their API, and ‘language=en’ simply means only English streams.

The last one, ‘after,’ is the interesting one, that’s the one I need to pass my cursor to, to get the next page of results. If it’s empty, I get the very first page. I then wrap it in a do/while loop, because as soon as the results returned from the API is less than 100, I know I’ve reached the end, and I can break out of the loop.

I’ll wrap all that in a sweet and simple function I can use later.

function Get-TwitchStream {
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [string]$ClientID,

        [Parameter(Mandatory)]
        [int]$GameID,

        [string]$Language = 'en'
    )

    $headers = @{
        "client-id" = $ClientID
    }

    $result = $null
    $uriTemplate = "https://api.twitch.tv/helix/streams?game_id={0}&first=100&language={1}&after={2}"

    do {
        $cursor = ""

        if ($result) { 
            $cursor = $result.pagination.cursor
        }

        $uri = $uriTemplate -f $GameID, $Language, $cursor
        $result = Invoke-RestMethod -Method Get -Headers $headers -Uri $uri
        $result.data
    } while ($result.data.Count -eq 100)
}

Conclusion

Now I have a simple PowerShell function that can easily query information about a stream on Twitch. And it feels great using PowerShell to solve a… well, not a problem… a curiosity?

Happy hacking.

  1. Tags: