Contents

Getting OAuth Access Tokens

Twitch APIs require access tokens to access resources. Depending on the resource you’re accessing, you’ll need a user access token or app access token. The API’s reference content identifies the type of access token you’ll need. The simple difference between the two types of tokens is that a user access token lets you access a user’s sensitive data (with their permission) and an app access token lets you access their non-sensitive data only (and doesn’t require the user’s permission).

If the APIs you’re calling require an OAuth app or user access token, use one of the following flows to get the token:

Flow Token Type Description
Implicit grant flow User access token Use this flow if your app does not use a server. For example, use this flow if your app is a client-side JavaScript app or mobile app.
Client credentials grant flow App access token Use this flow if your app uses a server, can securely store a client secret, and can make server-to-server requests to the Twitch API. This flow is meant for apps that only need an app access token.
Authorization code grant flow User access token Use this flow if your app uses a server, can securely store a client secret, and can make server-to-server requests to the Twitch API.
Device code grant flow User access token Use this flow if your app is run on a client with limited input capabilities, such as set-top boxes or video games.

NOTE Third-party apps that call the Twitch APIs and maintain an OAuth session must call the /validate endpoint to verify that the access token is still valid. Read more

Implicit grant flow

This flow is meant for apps that don’t use a server, such as client-side JavaScript apps or mobile apps.

To get a user access token using the implicit grant flow, navigate the user to https://id.twitch.tv/oauth2/authorize. For example, if your service is a website, you can add an HTML hyperlink for the user to click.

<a href="https://id.twitch.tv/oauth2/authorize?[parameters]">Connect with Twitch</a>

Specify the following query parameters as appropriate for your application.

Parameter Required? Type Description
client_id Yes String Your app’s registered client ID.
force_verify No Boolean Set to true to force the user to re-authorize your app’s access to their resources. The default is false.
redirect_uri Yes URI Your app’s registered redirect URI. The access token is sent to this URI.
response_type Yes String Must be set to token.
scope Yes String A space-delimited list of scopes. The APIs that you’re calling identify the scopes you must list. You must URL encode the list.
state No String Although optional, you are strongly encouraged to pass a state string to help prevent Cross-Site Request Forgery (CSRF) attacks. The server returns this string to you in your redirect URI (see the state parameter in the fragment portion of the URI). If this string doesn’t match the state string that you passed, ignore the response. The state string should be randomly generated and unique for each OAuth request.

The following URI is an example of the URI that you’ll navigate to in your web browser control (the URI is formatted for easier reading).

https://id.twitch.tv/oauth2/authorize
    ?response_type=token
    &client_id=hof5gwx0su6owfnys0yan9c87zr6t
    &redirect_uri=http://localhost:3000
    &scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls
    &state=c3ab8aa609ea11e793ae92361f002671

If the user is logged into Twitch, Twitch asks them to authorize your application’s access to the specified resources. If they’re not logged in, Twitch first asks them to log in and then asks them to authorize your application.

If the user authorizes your application by clicking Authorize, the server sends the access token to your redirect URI in the fragment portion of the URI (see the access_token parameter):

http://localhost:3000/
    #access_token=73d0f8mkabpbmjp921asv2jaidwxn
    &scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls
    &state=c3ab8aa609ea11e793ae92361f002671
    &token_type=bearer

NOTE In JavaScript, you can access the fragment using document.location.hash.

If the user didn’t authorize your app, the server sends the error code and description to your redirect URI (see the error and error_description query parameters).

http://localhost:3000/
    ?error=access_denied
    &error_description=The+user+denied+you+access
    &state=c3ab8aa609ea11e793ae92361f002671

Client credentials grant flow

The client credentials grant flow is meant only for server-to-server API requests that use an app access token.

To get an access token, send an HTTP POST request to https://id.twitch.tv/oauth2/token. Set the following x-www-form-urlencoded parameters as appropriate for your app.

Parameter Required? Type Description
client_id Yes String Your app’s registered client ID.
client_secret Yes String Your app’s registered client secret.
grant_type Yes String Must be set to client_credentials.

The following example shows the parameters in the body of the POST (the parameters are formatted for easier reading).

client_id=hof5gwx0su6owfnys0yan9c87zr6t
&client_secret=41vpdji4e9gif29md0ouet6fktd2
&grant_type=client_credentials

If the request succeeds, it returns an access token.

{
  "access_token": "jostpf5q0uzmxmkba9iyug38kjtgh",
  "expires_in": 5011271,
  "token_type": "bearer"
}

Authorization code grant flow

This flow is meant for apps that use a server, can securely store a client secret, and can make server-to-server requests to the Twitch API. To get a user access token using the authorization code grant flow, your app must Get the user to authorize your app and then Use the authorization code to get a token.

Get the user to authorize your app

The first step is to get the user to authorize your application’s access to their resources. To get the authorization, in your web browser control, navigate the user to https://id.twitch.tv/oauth2/authorize. For example, if your service is a website, you can add an HTML hyperlink for the user to click.

<a href="https://id.twitch.tv/oauth2/authorize?[parameters]">Connect with Twitch</a>

Specify the following query parameters as appropriate for your application.

Parameter Required? Type Description
client_id Yes String Your app’s registered client ID.
force_verify No Boolean Set to true to force the user to re-authorize your app’s access to their resources. The default is false.
redirect_uri Yes URI Your app’s registered redirect URI. The authorization code is sent to this URI.
response_type Yes String Must be set to code.
scope Yes String A space-delimited list of scopes. The APIs that you’re calling will identify the scopes you must list. You must URL encode the list.
state No String Although optional, you are strongly encouraged to pass a state string to help prevent Cross-Site Request Forgery (CSRF) attacks. The server returns this string to you in your redirect URI (see the state parameter in the fragment portion of the URI). If this string doesn’t match the state string that you passed, ignore the response. The state string should be randomly generated and unique for each OAuth request.

The following URI shows an example request that you’ll navigate to in your web browser control (the URI is formatted for easier reading).

https://id.twitch.tv/oauth2/authorize
    ?response_type=code
    &client_id=hof5gwx0su6owfnys0nyan9c87zr6t
    &redirect_uri=http://localhost:3000
    &scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls
    &state=c3ab8aa609ea11e793ae92361f002671

If the user is logged into Twitch, Twitch asks them to authorize your application’s access to the specified resources. If they’re not logged in, Twitch first asks them to log in and then asks them to authorize your application.

If the user authorized your app by clicking Authorize, the server sends the authorization code to your redirect URI (see the code query parameter):

http://localhost:3000/
    ?code=gulfwdmys5lsm6qyz4xiz9q32l10
    &scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls
    &state=c3ab8aa609ea11e793ae92361f002671

If the user didn’t authorize your app, the server sends the error code and description to your redirect URI (see the error and error_description query parameters):

http://localhost:3000/
    ?error=access_denied
    &error_description=The+user+denied+you+access
    &state=c3ab8aa609ea11e793ae92361f002671

Use the authorization code to get a token

The second step in this flow is to use the authorization code (see above) to get an access token and refresh token.

To get the tokens, send an HTTP POST request to https://id.twitch.tv/oauth2/token. Set the following x-www-form-urlencoded parameters in the body of the POST.

Parameter Required? Type Description
client_id Yes String Your app’s registered client ID.
client_secret Yes String Your app’s registered client secret.
code Yes String The code that the /authorize response returned in the code query parameter.
grant_type Yes String Must be set to authorization_code.
redirect_uri Yes URI Your app’s registered redirect URI.

The following example shows the parameters in the body of the POST (the parameters are formatted for easier reading).

client_id=hof5gwx0su6owfnys0yan9c87zr6t
&client_secret=41vpdji4e9gif29md0ouet6fktd2
&code=gulfwdmys5lsm6qyz4xiz9q32l10
&grant_type=authorization_code
&redirect_uri=http://localhost:3000

If the request succeeds, it returns an access token and refresh token.

{
  "access_token": "rfx2uswqe8l4g1mkagrvg5tv0ks3",
  "expires_in": 14124,
  "refresh_token": "5b93chm6hdve3mycz05zfzatkfdenfspp1h1ar2xxdalen01",
  "scope": [
    "channel:moderate",
    "chat:edit",
    "chat:read"
  ],
  "token_type": "bearer"
}

When the access token expires, use the refresh token to get a new access token. For information about using refresh tokens, see Refreshing Access Tokens.

Device code grant flow

This flow is designed for applications which do not use a server and are located on a stand alone device, such as a set-top box or a video game console.

Device Code Grant Flow (DCF) allows for public and confidential client types. The major differences between a public and confidential client type is that public clients:

Although the public clients do not need a client secret to obtain an access token there are some important details to be noted about the DCF related refresh tokens. For more information about using refresh tokens, see Refreshing Access Tokens:

Generally, if you device is secure, then confidential is the client type you should use, however if your application is on a more open platform (such as windows) we suggest using public.

Starting the DCF Flow for your user

The first step is to make the following cURL command from your client. This cURL command starts a device authorization grant code flow for your client.

Specify the following query parameters as appropriate for your application.

Parameter Required? Type Description
client_id Yes String Your app’s registered Client ID.
scopes Yes String A space-delimited list of scopes. The APIs that you’re calling identify the scopes you must list. You must URL encode the list.
    curl --location 'https://id.twitch.tv/oauth2/device' \
    --form 'client_id="<clientID>"' \
    --form 'scopes="<scopes>"'

The response to this call will contain:

Parameter Type Description
device_code String The identifier for a given user.
expires_in Int Time until the code is no longer valid
interval Int Time until another valid code can be requested
user_code String The code that the user will use to authenticate
verification_uri String The address you will send users to, to authenticate
    {
       "device_code": "ike3GM8QIdYZs43KdrWPIO36LofILoCyFEzjlQ91",
       "expires_in": 1800,
       "interval": 5,
       "user_code": "ABCDEFGH",
       "verification_uri": "https://www.twitch.tv/activate?public=true&device-code=ABCDEFGH"
    }

activate your device page image

Authorization Step

The user is presented with an authorization screen to review the scopes and complete the authorization.

access page and scopes requested

Obtaining the refresh token/access token pair

The next step for the client is to obtain the refresh token/access token pair for this current completed authorization. To do that we will utilize the device_code sent in the response of the first step. This grant_type is the RFC standard urn:ietf:params:oauth:grant-type:device_code, which signals our Authorization server that the client is trying to exchange the device code for a refresh_token/access_token pair.

cURL Request

Parameter Required Type Description
location Yes String URL used to request a token from Twitch. Will always be the same.
client_id Yes String Your app’s registered client ID.
scopes Yes String A space-delimited list of scopes. The APIs that you’re calling identify the scopes you must list. You must URL encode the list.
device_code Yes String The code that will authenticate the user.
grant_type Yes String Must be set to urn:ietf:params:oauth:grant-type:device_code.
    curl --location 'https://id.twitch.tv/oauth2/token' \
    --form 'client_id="<client_id>"' \
    --form 'scopes="<scopes>"' \
    --form 'device_code="<device_code>"' \
    --form 'grant_type="urn:ietf:params:oauth:grant-type:device_code"'

Response

Parameter Type Description
access_token String The authenticated token, to be used for various API endpoints and EventSub subscriptions.
expires_in Int Time until the code is no longer valid.
refresh_token String A token used to refresh the access token.
scope String An array of the scopes requested.
token_type String Will generally be “bearer”.
    {
       "access_token": "<access_token>",
       "expires_in": <some_int_value>,
       "refresh_token": "<refresh_token>",
       "scope": [
           "<scopes>"
       ],
       "token_type": "bearer"
    }

Once the access_token and refresh_tokens are received, the client should store these tokens for future exchange token calls using the refresh_token grant type which is highlighted in the step 5.

Before the user completes the authorization, the client cannot obtain the tokens, in this scenario we will send the following response when the client attempts to obtain the token using the device code.

    {
       "status": 400,
       "message": "authorization_pending"
    }

The device_code is one time use only, once the device_code has been used to obtain the tokens the client will receive the following response from the authorization server.

    {
       "status": 400,
       "message": "invalid device code"
    }

Finally a client can keep using the refresh_token grant to exchange a refresh_token for a new access_token. As mentioned earlier the refresh_token is one time use only and will be invalid once the token is exchanged. The client will then be presented with the following response if used more than once.

    {
       "status": 400,
       "message": "Invalid refresh token"
    }

Examples of the four flows

If you don’t want to write code to test the OAuth flows in this topic, try the following options. Before continuing, you’ll need to register an app to get a client ID and secret that you can use below. When registering your app, use http://localhost:3000 for your redirect URI.

Implicit flow example

Open your favorite browser and enter the following URI in the address bar. Substitute your client ID for the placeholder string.

https://id.twitch.tv/oauth2/authorize?response_type=token&client_id=<your client id goes here>&redirect_uri=http://localhost:3000&scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls&state=c3ab8aa609ea11e793ae92361f002671

If you’re not already signed in to your Twitch account, you’ll be asked to sign in. If this client ID hasn’t previously requested access to your Poll resource, you’ll be asked to give consent. If you want to always force consent, include the force_verify query parameter.

If you consented, the address bar is set to your redirect URI and it contains the access token (see access_token in the URI’s fragment).

http://localhost:3000/#access_token=wt6oxekssgvj53dkf38grzyzh2xe&scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls&state=c3ab8aa609ea11e793ae92361f002671&token_type=bearer

Authorization code flow example

Open your favorite browser and enter the following URI in the address bar. Substitute your client ID for the placeholder string.

https://id.twitch.tv/oauth2/authorize?response_type=code&client_id=<your client id goes here>&redirect_uri=http://localhost:3000&scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls&state=c3ab8aa609ea11e793ae92361f002671

If you’re not already signed in to your Twitch account, you’ll be asked to sign in. If this client ID hasn’t previously requested access to your Poll resource, you’ll be asked to give consent. If you want to always force consent, include the force_verify query parameter.

If you consented, the address bar is set to your redirect URI and it contains the authorization code (see the code parameter).

http://localhost:3000/?code=17038swieks1jh1hwcdr36hekyui&scope=channel%3Amanage%3Apolls+channel%3Aread%3Apolls&state=c3ab8aa609ea11e793ae92361f002671

Open a terminal window and enter the following cURL POST command (you’ll need cURL installed on your computer). Replace the placeholder strings and the authorization code with your values.

curl -X POST 'https://id.twitch.tv/oauth2/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=<your client id goes here>&client_secret=<your client secret goes here>&code=17038swieks1jh1hwcdr36hekyui&grant_type=authorization_code&redirect_uri=http://localhost:3000'

The response contains a JSON object with the access token and refresh token.

{
  "access_token": "fvc8xeeajsh0zkunt6fby67rnyux1",
  "expires_in": 15485,
  "refresh_token": "e2zyj5itwcmlg2clbcnd1wqlibypzjjydwu26bfhqhx1klp2o",
  "scope": [
    "channel:manage:polls",
    "channel:read:polls"
  ],
  "token_type": "bearer"
}

Client credentials flow example

Open a terminal window and enter the following cURL POST command (you’ll need cURL installed on your computer).

curl -X POST 'https://id.twitch.tv/oauth2/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=<your client id goes here>&client_secret=<your client secret goes here>&grant_type=client_credentials'

The response contains a JSON object with the access token.

{
  "access_token": "jostpf5q0puzmxmkba9iyug38kjtg",
  "expires_in": 5011271,
  "token_type": "bearer"
}

Device code flow example

The device will make a cURL request with requested scopes.

curl -X POST 'https://id.twitch.tv/oauth2/device' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=<Your client id here>&scopes=<Your scope here>'

The response will contain a URI.

{
  "device_code": "ikeYZs43KdrWPIO363GM8QIdLofILoCyFEzjlQ91",
  "expires_in": 1800,
  "interval": 5,
  "user_code": "ABCDEFGH",
  "verification_uri": "https://www.twitch.tv/activate?public=true&device-code=ABCDEFGH"
}

The device will show the user the URI to navigate to, in the above example it’s https://www.twitch.tv/activate?public=true&device-code=ABCDEFGH.

Once the user has accepted the authorization the device will call

curl --location 'https://id.twitch.tv/oauth2/token' \
--form'client_id="0mmkby2n450y6ho3s2b4xth9fjggz1"' \
--form'scope="channel:manage:broadcast"' \
--form'device_code="ike3GM8QIdYZs43KdrWPIO36LofILoCyFEzjlQ91"' \
--form'grant_type="urn:ietf:params:oauth:grant-type:device_code"'

Which will get a response with the access token and the refresh token.

{
  "access_token": "<access_token>",
  "expires_in": 14820,
  "refresh_token": "<refresh_token>",
  "scope": [
    "user:edit"
    ],
  "token_type": "bearer"
}