OAuth 2.0

This documentation is intended to be used for the OAuth 2.0 private beta. To sign up for this beta please use this form. Learn more in our forum post.


We are currently building and testing OAuth 2.0, including a related set of updated authorization scopes as part of a beta to select developers. OAuth 2.0 is an industry-standard authorization protocol that allows for greater control over an application’s scope, and authorization flows across multiple devices. 

  • This beta program is currently limited in a few ways, so that you can safely test the new functionality and we can safely collect issues and feedback:
  • Since this is a beta program, and not yet production-ready, we recommend that you avoid connecting to any endpoints in a production environment.
  • We have enabled a specific application of your choosing for protocol enablement as well as an associated Twitter account for authorization flow.
  • There is no onboarding yet through the developer portal, as OAuth 2.0 is currently only available to participants in this beta program.
  • OAuth 2.0 should be added to the account you gave us.

We have enabled OAuth to be used with the App you specified. Only these enabled accounts can see the new consumer consent flows.


Scopes allow you to set granular access for your App so that your App only has the permissions that it needs. The scopes we have available to start with include the following:

Scope Description
Allows your App to read Tweets.  You will also be able to see Tweets from protected Tweets.
Get information about any account.
account.follows.read Allows your App to access information on which accounts follow you and accounts you follow.
Allows your App to follow and unfollow accounts.
offline.access Allows an OAuth 2.0 refresh token to be issued that can be used to obtain an access token. If this scope is not passed, we will not generate a refresh token.
Access all of the Spaces you can see.


OAuth 2.0 can only be used with Apps that are connected to a Project. Therefore, you should already have a Project and App with OAuth 2.0 enabled.

The endpoints currently supported with OAuth 2.0 include:

Endpoint Required scopes
GET /2/users/by
  • users.read 
  • tweet.read
GET /2/tweets
  • tweet.read
  • users.read
GET /2/tweets/:id
  • tweet.read
  • users.read
GET /2/users/:id/following
  • account.follows.read
POST /2/users/:id/following
  • account.follows.write
DELETE /2/users/:source_user_id/following/:target_user_id
  • account.follows.write
GET /2/spaces/:id
  • tweet.read
  • users.read
  • spaces.read
GET /2/spaces/by/creator_ids
  • tweet.read
  • users.read
  • spaces.read
GET /2/spaces
  • tweet.read
  • users.read
  • spaces.read
GET /2/users/:id/following/spaces
  • tweet.read
  • users.read
  • spaces.read

Rate limits

For the most part, the rate limits are the same as they are authenticating with OAuth 1.0a or bearer token authentication, with the exception of Tweet lookup and user lookup. We are increasing the per-App limit from 300 to 900 requests per 15 minutes while using OAuth 2.0 for Tweet lookup and user lookup. 


Grant types

We only provide authorization code with PKCE and refresh token as the supported grant types for this initial launch. We may provide more grant types in the future.


OAuth 2.0 Flow

OAuth 2.0 uses a similar flow to what we are currently using for OAuth 1.0a. You can check out a diagram and detailed explanation in our documentation on this subject



Term Description
Grant types 
The OAuth framework specifies several grant types for different use cases and a framework for creating new grant types. Examples include authorization code, client credentials, device code, and refresh token.
Confidential client
Clients are applications that can securely authenticate with the authorization server, for example, keeping their registered client secret safe.
Public client

Clients cannot use registered client secrets, such as applications running in a browser or mobile device.

Authorization code flow

Used by both confidential and public clients to exchange an authorization code for an access token.

An extension to the authorization code flow to prevent several attacks and to be able to perform the OAuth exchange from public clients securely.

Client ID

Can be found in the keys and tokens section of the developer portal under the header "Client ID." If you don't see this, please get in touch with our team directly. The Client ID will be needed to generate the authorize URL.

Redirect URI

Your callback URL. 

Authorization code
 A temporary code that the client will exchange for an access token.
Access token

This allows an application to hit APIs on behalf of users. Known as the auth_code. The auth_code has a time limit of 30 seconds once the App owner receives an approved auth_code from the user. You will have to exchange it with an access token within 30 seconds, or the auth_codewill expire.

Refresh token

Allows an application to obtain a new access token without prompting the user via the refresh token flow.


To construct an OAuth 2.0 authorize URL, you will need to ensure you have the following parameters in the authorization URL. 

Parameter Description
You will need to specify that this is a code with the word “code”. 
Can be found the developer portal under the header "Client ID".
redirect_uri Your callback URL. This value must correspond to one of the Callback URLs defined in your App settings.
A random string you provide to verify against CSRF attacks.
code_challenge PKCE parameter, a random secret for each request you make. You can use this tooling to generate an s256 PKCE code.
Specifies the method you are using to make a request (s256 OR plain).



With OAuth 2.0, you create an authorize URL, which you can use to allow a user to authenticate via an authentication flow, similar to “Sign In” with Twitter. 

An example of the URL you are creating is as follows: 



How to connect to the endpoints

To authenticate your users, your App will need to implement an authorization flow. This authorization flow lets you direct your users to an authorization dialog on Twitter. From there, the primary Twitter experience will show the authorization dialog and handle the authorization on behalf of your App. Your users will be able to authorize your App or decline permission. After the user makes their choice, Twitter will redirect the user to your App, where you can exchange the authorization code for an access token (if the user authorized your App), or handle a rejection (if the user did not authorize your App).


Steps to connect using OAuth 2.0

Step 1: Construct an Authorize URL

Your App will need to build an authorize URL to Twitter, indicating the scopes your App needs to authorize. 

For example, if your App needs to lookup Tweets, users and to manage follows, it should request the following scopes:


The URL will also contain the code_verifier and state parameters, in addition to the other required parameters.


Step 2: GET oauth2/authorize

Have the user authenticate and send the application an authorization code.

Example URL to redirect the user to:


An example URL with offline_access would look like this:


Upon successful authentication, your redirect_uri would receive a request containing the auth_code parameter. Your application should verify the state parameter.

Example request from client’s redirect:



Step 3: POST oauth2/token - Access Token

At this point, you can use the authorization code to create an access token and refresh token (only if offline.access scope is requested). You can make a POST request to the following endpoint:


You will need to pass in the Content-Type of application/x-www-form-urlencoded via a header.  Additionally, you should have in your request:code, grant_type, client_id and redirect_uri, and the code_verifier.

Example token request:

      curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'code=VGNibzFWSWREZm01bjN1N3dicWlNUG1oa2xRRVNNdmVHelJGY2hPWGxNd2dxOjE2MjIxNjA4MjU4MjU6MToxOmFjOjE' \--data-urlencode 'grant_type=authorization_code' \--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ \--data-urlencode 'redirect_uri=https://www.example.com' \--data-urlencode 'code_verifier=challenge'


You should see the following response:

    "token_type": "bearer",
    "expires_in": 7200,
    "access_token": "Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE",
    "scope": "tweet.moderate.write account.follows.write users.read account.follows.read tweet.read",
    "refresh_token": "bWRWa3gzdnk3WHRGU1o0bmRRcTJ5VUxWX1lZTDdJSUtmaWcxbTVxdEFXcW5tOjE2MjIxNDc3NDM5MTQ6MToxOnJ0OjE"


Step 4: Connect to the APIs 

You are now ready to connect to the endpoints using OAuth 2.0. To do so, you will request the API as you would using Bearer Token authentication. Instead of passing your Bearer Token, you’ll want to use the access token you generated in the last step. As a response, you should see the appropriate payload corresponding to the endpoint you are requesting.

GET Multiple Tweets
      curl --location --request GET 'https://api.twitter.com/2/tweets?ids=1261326399320715264,1278347468690915330' \--header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
GET Single Tweet
      curl --location --request GET 'https://api.twitter.com/2/tweets/1261326399320715264' \--header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
GET Multiple users by IDs
      curl --location --request GET 'https://api.twitter.com/2/users?ids=2244994945,6253282' \--header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'

GET Single user by ID
      curl --location --request GET 'https://api.twitter.com/2/users/2244994945' \--header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
GET Followers of user ID 
      curl --location --request GET 'https://api.twitter.com/2/users/1176196242566574085/following' \ --header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
Follow a user
      curl --header 'Content-Type: application/json' \ --header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE' \ --request POST \ --data '{"target_user_id": "2244994945"}' \ https://api.twitter.com/2/users/2750565428/following

Unfollow a user
      POST 'https://api.twitter.com/2/oauth2/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'refresh_token=bWRWa3gzdnk3WHRGU1o0bmRRcTJ5VUxWX1lZTDdJSUtmaWcxbTVxdEFXcW5tOjE2MjIxNDc3NDM5MTQ6MToxOnJ0OjE \--data-urlencode 'grant_type=refresh_token' \--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ'
Spaces endpoints

You can learn more about connecting to our Spaces endpoints with OAuth 2.0 in our documentation on the subject.

Step 5: POST oauth2/token - refresh token

A refresh token allows an application to obtain a new access token without prompting the user. You can create a refresh token by making a POST request to the following endpoint:


You will need to add in the Content-Typeapplication/x-www-form-urlencoded via a header. In addition, you will also need to pass in your refresh_token, set your grant_type to be a refresh_token, and define your client_id.

      POST 'https://api.twitter.com/2/oauth2/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'refresh_token=bWRWa3gzdnk3WHRGU1o0bmRRcTJ5VUxWX1lZTDdJSUtmaWcxbTVxdEFXcW5tOjE2MjIxNDc3NDM5MTQ6MToxOnJ0OjE \--data-urlencode 'grant_type=refresh_token' \--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ'


Step 6: POST oauth2/revoke - Revoke Token

A revoke token invalidates an access token or refresh token. This is used to enable a "log out" feature in clients, allowing you to clean up any security credentials associated with the authorization flow that may no longer be necessary. The revoke token is for an App to revoke a token and not a user. You can create a revoke token request by making a POST request to the following URL if the App wants to programmatically revoke the access given to it:


You will need to pass in the Content-Type of application/x-www-form-urlencoded via a header, your token, your client_id, and set the token_type_hint to be equal to the access_token/refresh_token.

In some cases, a user may wish to revoke access given to an App. A user can revoke access by visiting the connected Apps page.

      curl --location --request POST 'https://api.twitter.com/2/oauth2/revoke' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'token=Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE' \--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ \--data-urlencode 'token_type_hint=access_token'


Additional resources

To help you get started with using OAuth 2.0, we have some resources created. 

These include the following:



To give us any feedback or report any bugs, or get in touch with our team for additional please send us an email at OAuth2Beta@twitter.com.

Was this document helpful?
Thank you

Thank you for the feedback. We’re really glad we could help!

Thank you for the feedback. How could we improve this document?
Thank you for the feedback. Your comments will help us improve our documents in the future.