Introduction

The v2 Post counts endpoints allow developers to understand and retrieve the volume of data for a given query.  This can be beneficial for a number of reasons, including:

  • Understand the Post volume for a keyword to build visualizations, such as trendlines.

  • Understanding the time period in which an event or conversation occurred, to ensure your query captures the relevant data

  • Understanding how many Posts a search query will return, in order to refine your query, before using the recent search or full-archive search endpoints. Please note: The counts will not always match the result that will be returned from search endpoints because the search endpoints go through additional compliance that the counts endpoints do not go through

  • Understanding the size of the conversation around a topic, without actually having to pull the raw data, and put Posts against your monthly Post cap

When developing a query, you will be limited to a certain query length and to specific operators based on your access level

  • If you are using a Project with Pro access, you can use all available operators, and use queries up to 1024 characters in length. 

  • If you are using a Project with Enterprise access, you can use all available operators, and use queries up to 4096 characters in length. 

You can also specify the granularity (which can be day, hour, or minute) as well as the time period for which you need the Post counts (using the start_time and end_time parameters). The default time granularity that this endpoint uses is hour, which means if you do not specify the granularity parameter, the endpoint will give you the Post counts per hour, for the last 7 days.

Account setup

To access these endpoints, you will need:

Learn more about getting access to the X API v2 endpoints in our getting started guide.

Recent Post counts

The recent Post counts endpoint allows you to programmatically retrieve the numerical count of Posts for a query, over the last seven days. This endpoint is available via to anyone using keys and tokens that are associated with an App within a Project and uses OAuth 2.0 App-Only for authentication.

Full-archive Post counts

Academic Research or Enterprise access only

The full-archive Post counts endpoint allows you to programmatically retrieve the numerical count of Posts for a query, from the entire archive of public Posts. Currently, this endpoint is only available to those that have been approved for Academic Research or Enterprise access and use the OAuth 2.0 App-Only for authentication.

One example: You could use the full-archive Post counts endpoint to see the number of Posts for the hashtag #SOSHurricaneHarvey per day between August and September 2017.

Please note: The counts endpoint paginates at 31 days per response. For example, setting a day granularity, will return the count of results per day for 31 days per page.  Setting an hour granularity, will return the count of results per hour for 744 (31 days x 24 hours) hours per page.  If you do not specify the granularity and time period, this endpoint will give you Post counts for a query per hour, for the last 30 days.

Quick Start

Getting started with the recent Post counts endpoint

This quick start guide will help you make your first request to the recent Post counts endpoint using Postman, a graphical tool that allows you to send HTTP requests.

If you would like to see sample code in different programming languages, please visit our X API v2 sample code GitHub repository. 

Prerequisites

To complete this guide, you will need to have a set of keys and tokens to authenticate your request. You can generate these keys and tokens by following these steps:

  • Sign up for a developer account and receive approval.
  • Create a Project and an associated developer App in the developer portal.
  • Navigate to your App’s “Keys and tokens” page to generate the required credentials. Make sure to save all credentials in a secure location.

Steps to build a recent Post counts request

Step one: Start with a tool or library

There are several different tools, code examples, and libraries that you can use to make a request to this endpoint, but we are going to use the Postman tool here to simplify the process.

To load X API v2 Postman collection into your environment, please click on the following button:

Once you have the X API v2 collection loaded in Postman, navigate to the Post counts > Recent Post counts request.

Step two: Authenticate your request

To properly make a request to the X API, you need to verify that you have permission. To do so with this endpoint, you must authenticate your request with the OAuth 2.0 App-Only authentication methods.

You must add your keys and tokens, specifically the App Access Token (also known as the App-only Bearer Token) to Postman. You can do this by selecting the environment named “X API v2” in the top-right corner of Postman and adding your keys and tokens to the “initial value” and “current value” fields (by clicking the eye icon next to the environment dropdown).

This variable will automatically be pulled into the request’s authorization tab if you’ve done this correctly.  

Step three: Create a query

Each recent Post counts request requires a singlequery. For this example, we are going to use a query that matches on Posts posted by the @XDevelopers account. For this query we use the from: operator and set it to XDevelopers (case insensitive):

from:XDevelopers

In Postman, navigate to the “Params” tab and enter this ID, or a string of Post IDs separated by a comma, into the “Value” column of the ids parameter.

KeyValueDescription
queryfrom:XDevelopersQuery to submit to the recent Post counts endpoint

Step four (optional): Specify the granularity of the request

If you click the ‘Send’ button after step three, you will get the default recent Post counts: by hour for the last seven days. If you want to get recent Post counts by day, you will have to add the granularity parameter with a value of day.

In Postman, navigate to the “Params” tab and day into the “Value” column of the granularity parameter.

KeyValueDescription
granularitydayThe granularity for the Post counts results. Possible values are day, hour or minute

You should now see the following URL next to the “Send” button:

https://api.x.com/2/tweets/counts/recent?query=from%3AXDevelopers&granularity=day

Step five: Make your request and review your response

Once you have everything set up, hit the “Send” button and you will receive the following response:

{
   "data": [
       {
           "end": "2021-06-16T00:00:00.000Z",
           "start": "2021-06-15T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-06-17T00:00:00.000Z",
           "start": "2021-06-16T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-06-18T00:00:00.000Z",
           "start": "2021-06-17T00:00:00.000Z",
           "tweet_count": 2
       },
       {
           "end": "2021-06-19T00:00:00.000Z",
           "start": "2021-06-18T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-06-20T00:00:00.000Z",
           "start": "2021-06-19T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-06-21T00:00:00.000Z",
           "start": "2021-06-20T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-06-22T00:00:00.000Z",
           "start": "2021-06-21T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-06-23T00:00:00.000Z",
           "start": "2021-06-22T00:00:00.000Z",
           "tweet_count": 2
       }
   ],
   "meta": {
       "total_tweet_count": 6
   }
}

Getting started with the full-archive Post counts     endpoint

This quick start guide will help you make your first request to the full-archive Post counts endpoint using Postman, a graphical tool that alows you to make HTTP requests.

If you would like to see sample code in different programming languages, please visit our X API v2 sample code GitHub repository. 

Prerequisites

The full-archive Post counts endpoint is currently only available to those that have Pro or Enterprise access. In order to use this endpoint, you must apply for Pro or Enterprise access

In addition to being approved for access, you will need to have a set of keys and tokens to authenticate your request. You can generate these keys and tokens by following these steps:

  • Navigate to your Project with Enterprise access in the developer portal and make sure you have an associated developer App within that Project.

  • Navigate to your App’s “Keys and tokens” page to generate the required credentials. Make sure to save all credentials in a secure location.

Steps to build a full-archive Post counts request

Step one: Start with a tool or library

There are several different tools, code examples, and libraries that you can use to make a request to this endpoint, but we are going to use the Postman tool here to simplify the process.

To load X API v2 Postman collection into your environment, please click on the following button:

Once you have the X API v2 collection loaded in Postman, navigate to the Post counts > Full-archive Post counts request.

Step two: Authenticate your request

To properly make a request to the X API, you need to verify that you have permission. To do so with this endpoint, you must authenticate your request with the OAuth 2.0 App-Only authentication methods.

You must add your keys and tokens, specifically the App Access Token (also known as the App-only Bearer Token) to Postman. You can do this by selecting the environment named “X API v2” in the top-right corner of Postman and adding your keys and tokens to the “initial value” and “current value” fields (by clicking the eye icon next to the environment dropdown).

This variable will automatically be pulled into the request’s authorization tab if you’ve done this correctly.  

Step three: Create a query

Each full-archive Post counts request requires a single query. For this example, we are going to use a query that matches on Posts posted by the @XDevelopers account. For this query we use the from operator and set it to XDevelopers (case insensitive):

from:XDevelopers

In Postman, navigate to the “Params” tab and enter this ID, or a string of Post IDs separated by a comma, into the “Value” column of the ids parameter.  

KeyValueDescription
queryfrom:XDevelopersQuery to submit to the full-archive Post counts endpoint

Step four (optional): Specify the granularity and time period

If you click the ‘Send’ button after step three, you will get the default full-archive Post counts: by hour for the last 30 days. If you want to get full-archive Post counts by day, you will have to add the granularity parameter with a value of day. If you want Post counts for more than 30 days ago, you will have to specify the start_time and end_time parameters with the desired values. 

In Postman, navigate to the “Params” tab and add the following key:value pair to the “Query Params” table:

KeyValueDescription
granularitydayThe granularity for the Post counts results. Possible values are day, hour or minute
start_time2021-05-01T00:00:00ZThe oldest UTC timestamp from which the Posts will be provided
end_time2021-06-01T00:00:00ZThe oldest UTC timestamp from which the Posts will be provided.

You should now see the following URL next to the “Send” button:

https://api.x.com/2/tweets/counts/all?query=from%3AXDevelopers&start_time=2021-05-01T00:00:00Z&end_time=2021-06-01T00:00:00Z&granularity=day

Step five: Make your request and review your response

Once you have everything set up, hit the “Send” button and you will receive a response similar to the following:

{
   "data": [
       {
           "end": "2021-05-02T00:00:00.000Z",
           "start": "2021-05-01T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-03T00:00:00.000Z",
           "start": "2021-05-02T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-04T00:00:00.000Z",
           "start": "2021-05-03T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-05T00:00:00.000Z",
           "start": "2021-05-04T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-06T00:00:00.000Z",
           "start": "2021-05-05T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-07T00:00:00.000Z",
           "start": "2021-05-06T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-08T00:00:00.000Z",
           "start": "2021-05-07T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-09T00:00:00.000Z",
           "start": "2021-05-08T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-10T00:00:00.000Z",
           "start": "2021-05-09T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-11T00:00:00.000Z",
           "start": "2021-05-10T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-12T00:00:00.000Z",
           "start": "2021-05-11T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-13T00:00:00.000Z",
           "start": "2021-05-12T00:00:00.000Z",
           "tweet_count": 6
       },
       {
           "end": "2021-05-14T00:00:00.000Z",
           "start": "2021-05-13T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-15T00:00:00.000Z",
           "start": "2021-05-14T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-16T00:00:00.000Z",
           "start": "2021-05-15T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-17T00:00:00.000Z",
           "start": "2021-05-16T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-18T00:00:00.000Z",
           "start": "2021-05-17T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-19T00:00:00.000Z",
           "start": "2021-05-18T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-20T00:00:00.000Z",
           "start": "2021-05-19T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-21T00:00:00.000Z",
           "start": "2021-05-20T00:00:00.000Z",
           "tweet_count": 8
       },
       {
           "end": "2021-05-22T00:00:00.000Z",
           "start": "2021-05-21T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-23T00:00:00.000Z",
           "start": "2021-05-22T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-24T00:00:00.000Z",
           "start": "2021-05-23T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-25T00:00:00.000Z",
           "start": "2021-05-24T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-26T00:00:00.000Z",
           "start": "2021-05-25T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-27T00:00:00.000Z",
           "start": "2021-05-26T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-28T00:00:00.000Z",
           "start": "2021-05-27T00:00:00.000Z",
           "tweet_count": 1
       },
       {
           "end": "2021-05-29T00:00:00.000Z",
           "start": "2021-05-28T00:00:00.000Z",
           "tweet_count": 2
       },
       {
           "end": "2021-05-30T00:00:00.000Z",
           "start": "2021-05-29T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-05-31T00:00:00.000Z",
           "start": "2021-05-30T00:00:00.000Z",
           "tweet_count": 0
       },
       {
           "end": "2021-06-01T00:00:00.000Z",
           "start": "2021-05-31T00:00:00.000Z",
           "tweet_count": 0
       }
   ],
   "meta": {
       "total_tweet_count": 22
   }
}

Step six: Paginate through your results

If the ‘meta’ object in your response also contains next_token, you can pass its value to the next_token query parameter.

KeyValueDescription
next_tokenYou will add the next_token that you pull from your previous request’s meta object and add it here.If your latest request does not deliver the remainder of the results, you will receive a next_token in the meta object. You will pull the value of that field and add it as the value of the next_token parameter in your next request, holding all other request parameters constant.

Once you have the right value for next_token set, hit the “Send” button and you will receive the next page of results.

How to integrate with the Posts counts endpoints

This page contains information on several tools and key concepts that you should be aware of as you integrate the recent or full-archive Post counts endpoints into your system. We’ve split the page into the following sections:

Helpful tools

Before we start to explore some key concepts, we recommend that you use one of the following tools or code samples to start testing the functionality of these endpoints.

Code samples

Interested in getting set up with these endpoints with some code in your preferred coding language? We’ve got a handful of different code samples available that you can use as a starting point on our GitHub page, including a Python client.

Libraries

Take advantage of one of our many community third-party libraries to help you get started. You can find a library that works with the v2 endpoints by looking for the appropriate version tag.

Postman

Postman is a great tool that you can use to test out these endpoints. Each Postman request includes all of the given endpoint’s parameters to help you quickly understand what is available to you. To learn more about our Postman collections, please visit our Using Postman page.  

Key concepts

Authentication

All X API v2 endpoints require requests to be authenticated with a set of credentials, also known as keys and tokens. This specific endpoint requires the use of OAuth 2.0 Bearer Token, which means that you must pass a Bearer Token to make a successful request. You can either generate a Bearer Token from directly within a developer App, or generate one using the POST oauth2/token endpoint.

Developer portal, Projects, and developer Apps

To work with any X API v2 endpoints, you must have a developer account, set up a Project within that account, and created a developer App within that Project. Your keys and tokens within that developer App will work for the recent Post counts endpoints. If you would like to use the full-archive Post counts endpoint, or utilize the advanced operators and longer query length, you will need to have been approved for enterprise access.

Please visit our section on enterprise access to learn more.

Rate limits

Every day, many thousands of developers make requests to the X API. To help manage the volume, rate limits are placed on each endpoint that limits the number of requests that every developer can make on behalf of an app or on behalf of an authenticated user.

This endpoint is rate limited at the App-level, meaning that you, the developer, can only make a certain number of requests to this endpoint over a given period of time from any given App (assumed by the credentials that you are using). 

Building queries

The central feature of these endpoints is their use of a single query to filter the Posts into the counts that deliver to you. These queries are made up of operators that match on Post and user attributes, such as message keywords, hashtags, and URLs. Operators can be combined into queries with boolean logic and parentheses to help refine the query’s matching behavior.

You can use our guide on how to build a query to learn more.

We have also written a more in-depth tutorial on how to [build high-quality filters for getting X data]https://developer.x.com/en/docs/tutorials/building-high-quality-filters.  

Pagination

For recent Post counts, there is no next_token returned, which means that regardless of the granularity, you will get  the Post volume for the last 7 days in one API call.

For full-archive Post counts, you will get data for the last 30 days. For data more than 30 days, you will get a next_token which you can then use to paginate to get the additional data. 

Building queries for Post counts

The Post counts endpoints accept a single query with a GET request and return a set of historical Post counts that match the query.  Queries are made up of operators that are used to match on a variety of Post attributes. 

To learn more about how to create high-quality queries, visit the following tutorial: [Building high-quality filters for getting X data]https://developer.x.com/en/docs/tutorials/building-high-quality-filters

Table of contents

Building a query

Query limitations!

Your queries will be limited depending on which access level you are using. 

If you have Pro access, your query can be 512 characters long.

If you have Enterprise access, please reach out to your account manager. 

Operator availability

While most operators are available to any developer, there are several that are reserved for those that have been approved for Enterprise access. We list which access level each operator is available to in the list of operators table using the following labels:

  • Core operators: Available when using any Project.
  • Advanced operators: Available when using a Project with Enterprise access   

Operator types: standalone and conjunction-required

Standalone operators can be used alone or together with any other operators (including those that require conjunction).

For example, the following query will work because it uses the #hashtag operator, which is standalone:

#xapiv2

Conjunction-required operators cannot be used by themselves in a query; they can only be used when at least one standalone operator is included in the query. This is because using these operators alone would be far too general, and would match on an extremely high volume of Posts.

For example, the following queries are not supported since they contain only conjunction-required operators:

has:media has:links OR is:retweet

If we add in a standalone operator, such as the phrase “X data”, the query would then work properly. 

“X data” has:mentions (has:media OR has:links)

Boolean operators and grouping

If you would like to string together multiple operators in a single query, you have the following tools at your disposal:

AND logicSuccessive operators with a space between them will result in boolean “AND” logic, meaning that Posts will match only if both conditions are met. For example, snow day #NoSchool will match Posts containing the terms snow and day and the hashtag #NoSchool.
OR logicSuccessive operators with OR between them will result in OR logic, meaning that Posts will match if either condition is met. For example, specifying grumpy OR cat OR #meme will match any Posts containing at least the terms grumpy or cat, or the hashtag #meme.
NOT logic, negationPrepend a dash (-) to a keyword (or any operator) to negate it (NOT). For example, cat #meme -grumpy will match Posts containing the hashtag #meme and the term cat, but only if they do not contain the term grumpy. One common query clause is -is:retweet, which will not match on Retweets, thus matching only on original Posts, Quote Tweets, and replies. All operators can be negated, but negated operators cannot be used alone.
GroupingYou can use parentheses to group operators together. For example, (grumpy cat) OR (#meme has:images) will return either Posts containing the terms grumpy and cat, or Posts with images containing the hashtag #meme. Note that ANDs are applied first, then ORs are applied.

A note on negations

The operators -is:nullcast must always be negated.

Negated operators cannot be used alone.

Do not negate a set of operators grouped together in a set of parentheses. Instead, negate each individual operator. For example, instead of using skiing -(snow OR day OR noschool), we suggest that you use skiing -snow -day -noschool. 

Order of operations

When combining AND and OR functionality, the following order of operations will dictate how your query is evaluated.

  1. Operators connected by AND logic are combined first
  2. Then, operators connected with OR logic are applied

For example:

  • apple OR iphone ipad would be evaluated as apple OR (iphone ipad)
  • ipad iphone OR android would be evaluated as (iphone ipad) OR android

To eliminate uncertainty and ensure that your query is evaluated as intended, group terms together with parentheses where appropriate. 

For example:

  • (apple OR iphone) ipad
  • iphone (ipad OR android)  

Punctuation, diacritics, and case sensitivity

If you specify a keyword or hashtag query with character accents or diacritics, it will match Post text that contains both the term with the accents and diacritics, as well as those terms with normal characters. For example, queries with a keyword Diacrítica or hashtag #cumpleaños will match Diacrítica or #cumpleaños, as well as with Diacritica or #cumpleanos without the tilde í or eñe.

Characters with accents or diacritics are treated the same as normal characters and are not treated as word boundaries. For example, a query with the keyword cumpleaños would only match activities containing the word cumpleaños and would not match activities containing cumpleacumplean, or os.

All operators are evaluated in a case-insensitive manner. For example, the query cat will match Posts with all of the following: catCATCat.

The filtered stream matching behavior acts differently from Post counts. When building a filtered stream rule, know that keywords and hashtags that include accents and diacritics will only match on terms that also include the accent and diacritic, and will not match on terms that use normal characters instead. 

For example, filtered stream rules that include a keyword Diacrítica or hashtag #cumpleaños will only match the terms Diacrítica and #cumpleaños, and will not match on Diacritica or #cumpleanos without the tilde í or eñe

Specificity and efficiency

When you start to build your query, it is important to keep a few things in mind.

  • Using broad, standalone operators for your query such as a single keyword or #hashtag is generally not recommended since it will likely match on a massive volume of Posts. Creating a more robust query will result in a more specific set of matching Posts, and will hopefully increase the accuracy of your Post counts to help you find more valuable insights. 
    • For example, if your query was just the keyword happy you will likely get anywhere from 200,000 - 300,000 Posts per day.
    • Adding more conditional operators narrows your results, for example (happy OR happiness) place_country:GB -birthday -is:retweet
  • Writing efficient queries is also beneficial for staying within the characters query length restriction. The character count includes the entire query string including spaces and operators.
    • For example, the following query is 59 characters long: (happy OR happiness) place_country:GB -birthday -is:retweet

Quote Tweet matching behavior

When using the Post counts endpoints, operators will not match on the content from the original Post that was quoted, but will match on the content included in the Quote Tweet.

However, please note that filtered stream will match on both the content from the original Post that was quoted and the Quote Tweet’s content.  

Iteratively building a query

Test your query early and often

Getting a query to return the “right” results the first time is rare. There is so much on X that may or may not be obvious at first and the query syntax described above may be hard to match to your desired query.

As you build a query, it is important for you to periodically test it out using one of the Search Post endpoints to ensure that the Posts that are matching your query are relevant to your use case.

For this section, we are going to start with the following query and adjust it based on the results that we receive during our test: 

happy OR happiness

Use results to narrow the query

As you test the query with Search Posts, you should scan the returned Posts to see if they include the data that you are expecting and hoping to receive. Starting with a broad query and a superset of Post matches allows you to review the result and narrow the query to filter out undesired results.  

When we tested the example query, we noticed that we were getting Posts in a variety of different languages. In this situation, we want to only receive Posts that are in english, so we’re going to add the lang: operator:

(happy OR happiness) lang:en

The test delivered a number of Posts wishing people a happy birthday, so we are going to add -birthday as a negated keyword operator. We also want to only receive original Posts, so we’ve added the negated -is:retweet operator:

(happy OR happiness) lang:en -birthday -is:retweet

Adjust for inclusion where needed

If you notice that you are not receiving data via Search Posts that you expect and know that there are existing Posts that should return, you may need to broaden your query by removing operators that may be filtering out the desired data. 

For our example, we noticed that there were other Posts in our personal timeline that expressed the emotion that we are looking for and weren’t included in the test results. To ensure we have greater coverage, we are going to add the keywords, excited and elated.

(happy OR happiness OR excited OR elated) lang:en -birthday -is:retweet

Adjust for popular trends/bursts over the time period

Trends come and go on X quickly. Maintaining your query should be an active process. If you plan to use a query for a while, we suggest that you periodically check in on the data that you are receiving to see if you need to make any adjustments.

In our example, we notice that we started to receive some Posts that are wishing people a “happy holidays”. Since we don’t want these Posts included in our results, we are going to add a negated -holidays keyword.

(happy OR happiness OR excited OR elated) lang:en -birthday -is:retweet -holidays 

Once you’ve properly tested and iterated upon your query, you can start sending it with the Post counts endpoints to start to receive just the volume of Posts rather than the full Post payloads.

Adding a query to your request

To add your query to your request, you must use the query parameter. As with any query parameters, you must make sure to HTTP encode the query that you developed.

Here is an example of what this might look like using a cURL command. If you would like to use this command, please make sure to replace $BEARER_TOKEN with your own Bearer Token:

curl https://api.x.com/2/tweets/counts/recent?query=cat%20has%3Amedia%20-grumpy&tweet.fields=created_at&max_results=100 -H "Authorization: Bearer $BEARER_TOKEN"

Query examples

Tracking a natural disaster

The following query matched on original Posts coming from weather agencies and gauges that discuss Hurricane Harvey, which hit Houston in 2017.

Here is what the query would look like without the HTTP encoding:

has:geo (from:NWSNHC OR from:NHC_Atlantic OR from:NWSHouston OR from:NWSSanAntonio OR from:USGS_TexasRain OR from:USGS_TexasFlood OR from:JeffLindner1) -is:retweet

And here is what the query would look like with the HTTP encoding, the query parameter, and the recent Post counts URI:

https://api.x.com/2/tweets/counts/recent?query=-is%3Aretweet%20has%3Ageo%20(from%3ANWSNHC%20OR%20from%3ANHC\_Atlantic%20OR%20from%3ANWSHouston%20OR%20from%3ANWSSanAntonio%20OR%20from%3AUSGS\_TexasRain%20OR%20from%3AUSGS_TexasFlood%20OR%20from%3AJeffLindner1)

Reviewing the sentiment of a conversation

The next rule could be used to better understand the sentiment of the conversation developing around the hashtag, #nowplaying, but scoped to just Posts published within North America.

Here is what the two different queries, one for positive and one for negative, would look like without the HTTP encoding:

#nowplaying (happy OR exciting OR excited OR favorite OR fav OR amazing OR lovely OR incredible) (place_country:US OR place_country:MX OR place_country:CA) -horrible -worst -sucks -bad -disappointing

#nowplaying (horrible OR worst OR sucks OR bad OR disappointing) (place_country:US OR place_country:MX OR place_country:CA) -happy -exciting -excited -favorite -fav -amazing -lovely -incredible

And here is what the query would look like with the HTTP encoding, the query parameter, and the recent Post counts URI:

https://api.x.com/2/tweets/counts/recent?query=%23nowplaying%20(happy%20OR%20exciting%20OR%20excited%20OR%20favorite%20OR%20fav%20OR%20amazing%20OR%20lovely%20OR%20incredible)%20(place\_country%3AUS%20OR%20place\_country%3AMX%20OR%20place_country%3ACA)%20-horrible%20-worst%20-sucks%20-bad%20-disappointing

https://api.x.com/2/tweets/counts/recent?query=%23nowplaying%20(horrible%20OR%20worst%20OR%20sucks%20OR%20bad%20OR%20disappointing)%20(place\_country%3AUS%20OR%20place\_country%3AMX%20OR%20place_country%3ACA)%20-happy%20-exciting%20-excited%20-favorite%20-fav%20-amazing%20-lovely%20-incredible

Find Posts that relate to a specific Post annotation

This rule was built to filter for original Posts that included an image of a pet that is not a cat, where the language identified in the Post is Japanese. To do this, we used the context: operator to take advantage of thePost annotation functionality. We first used thePost lookup endpoint and the tweet.fields=context_annotations fields parameter to identify which domain.entity IDs we need to use in our query:

  • Posts that relate to cats return domain 66 (Interests and Hobbies category) with entity 852262932607926273 (Cats). 
  • Posts that relate to pets return domain 65 (Interests and Hobbies Vertical) with entity 852262932607926273 (Pets). 

Here is what the query would look like without the HTTP encoding:

context:65.852262932607926273 -context:66.852262932607926273 -is:retweet has:images lang:ja

And here is what the query would look like with the HTTP encoding, the query parameter, and the recent Post counts URI:

https://api.x.com/2/tweets/counts/recent?query=context%3A65.852262932607926273%20-context%3A66.852262932607926273%20-is%3Aretweet%20has%3Aimages%20lang%3Aja

Operators

OperatorTypeAvailabilityDescription
keywordStandaloneCoreMatches a keyword within the body of a Post. This is a tokenized match, meaning that your keyword string will be matched against the tokenized text of the Post body. Tokenization splits words based on punctuation, symbols, and Unicode basic plane separator characters. For example, a Post with the text “I like coca-cola” would be split into the following tokens: I, like, coca, cola. These tokens would then be compared to the keyword string used in your query. To match strings containing punctuation (for example coca-cola), symbol, or separator characters, you must wrap your keyword in double-quotes. Example: pepsi OR cola OR "coca cola"
emojiStandaloneCoreMatches an emoji within the body of a Post. Similar to a keyword, emojis are a tokenized match, meaning that your emoji will be matched against the tokenized text of the Post body. Note that if an emoji has a variant, you must wrap it in double quotes to add to a query. Example: (😃 OR 😡) 😬
"exact phrase match"StandaloneCoreMatches the exact phrase within the body of a Post. Example: ("X API" OR #v2) -"recent counts"
#StandaloneCoreMatches any Post containing a recognized hashtag, if the hashtag is a recognized entity in a Post. This operator performs an exact match, NOT a tokenized match, meaning the rule #thanku will match posts with the exact hashtag #thanku, but not those with the hashtag #thankunext. Example: #thankunext #fanart OR @arianagrande
@StandaloneCoreMatches any Post that mentions the given username, if the username is a recognized entity (including the @ character). Example: (@XDevelopers OR @API) -@X
$StandaloneAdvancedMatches any Post that contains the specified ‘cashtag’ (where the leading character of the token is the ‘character).NotethatthecashtagoperatorreliesonXssymbolsentityextractiontomatchcashtags,ratherthantryingtoextractthecashtagfromthebodyitself.Example:’ character). Note that the cashtag operator relies on X's ‘symbols’ entity extraction to match cashtags, rather than trying to extract the cashtag from the body itself. Example: `twtr OR @XDevelopers -$fb`
from:StandaloneCoreMatches any Post from a specific user. The value can be either the username (excluding the @ character) or the user’s numeric user ID. You can only pass a single username/ID per from: operator. Example: from:XDevelopers OR from:API -from:X
to:StandaloneCoreMatches any Post that is in reply to a particular user. The value can be either the username (excluding the @ character) or the user’s numeric user ID. You can only pass a single username/ID per to: operator. Example: to:XDevelopers OR to:API -to:X
url:StandaloneCorePerforms a tokenized match on any validly-formatted URL of a Post. This operator can matches on the contents of both the url or expanded_url fields. For example, a Post containing “You should check out X Developer Labs: https://t.co/c0A36SWil4” (with the short URL redirecting to https://developer.twitter.com) will match both the following rules: from:XDevelopers url:"https://developer.twitter.com" and from:XDevelopers url:"https://t.co". Tokens and phrases containing punctuation or special characters should be double-quoted.
retweets_of:StandaloneCoreMatches Posts that are Retweets of the specified user. The value can be either the username (excluding the @ character) or the user’s numeric user ID. You can only pass a single username/ID per retweets_of: operator. Example: retweets_of:XDevelopers OR retweets_of:API
context:StandaloneCoreMatches Posts with a specific domain id/entity id pair. You can only pass a single domain/entity per context: operator. Example: context:domain_id.entity_id. You can combine multiple domain/entities using the OR operator: (context:47.113922 9372198469633 OR context:11.1088514520308342784)
entity:StandaloneCoreMatches Posts with a specific entity string value. You can only pass a single entity: operator. Example: entity:"string declaration of entity/place". Please note that this is only available with recent search.
conversation_id:StandaloneCoreMatches Posts that share a common conversation ID. A conversation ID is set to the Post ID of a Post that started a conversation. As Replies to a Post are posted, even Replies to Replies, the conversation_id is added to its JSON payload. You can only pass a single conversation ID per conversation_id: operator. Example: conversation_id:1334987486343299072 (from:XDevelopers OR from:API)
list:StandaloneAdvancedMatches Posts posted by users who are members of a specified list. For example, if @XDevelopers and @API were members of List 123, and you included list:123 in your query, your response will only contain Posts that have been published by those accounts. You can find List IDs by using the List lookup endpoint. Example: list:123
place:StandaloneAdvancedMatches Posts tagged with the specified location or X place ID. Multi-word place names (“New York City”, “Palo Alto”) should be enclosed in quotes. You can only pass a single place per place: operator. Note: See the GET geo/search standard v1.1 endpoint for how to obtain X place IDs. Example: place:"new york city" OR place:seattle OR place:fd70c22040963ac7
place_country:StandaloneAdvancedMatches Posts where the country code associated with a tagged place/location matches the given ISO alpha-2 character code. You can find a list of valid ISO codes on Wikipedia. You can only pass a single ISO code per place_country: operator. Example: place_country:US OR place_country:MX OR place_country:CA
point_radius:StandaloneAdvancedMatches against the place.geo.coordinates object of the Post when present, and in X, against a place geo polygon, where the Place polygon is fully contained within the defined region. point_radius:[longitude latitude radius]. Units of radius supported are miles (mi) and kilometers (km). Radius must be less than 25mi. Longitude is in the range of ±180. Latitude is in the range of ±90. All coordinates are in decimal degrees. Rule arguments are contained within brackets, space delimited. Example: point_radius:[2.355128 48.861118 16km] OR point_radius:[-41.287336 174.761070 20mi]
bounding_box:StandaloneAdvancedMatches against the place.geo.coordinates object of the Post when present, and in X, against a place geo polygon, where the place polygon is fully contained within the defined region. bounding_box:[west_long south_lat east_long north_lat]. Width and height of the bounding box must be less than 25mi. Longitude is in the range of ±180. Latitude is in the range of ±90. All coordinates are in decimal degrees. Rule arguments are contained within brackets, space delimited. Example: bounding_box:[-105.301758 39.964069 -105.178505 40.09455]
is:retweetConjunction requiredCoreMatches on Retweets that match the rest of the specified rule. This operator looks only for true Retweets (for example, those generated using the Retweet button). Quote Tweets will not be matched by this operator. Example: data @XDevelopers -is:retweet
is:replyConjunction requiredCoreDeliver only explicit replies that match a rule. Can also be negated to exclude replies that match a query from delivery. Note: This operator is also available with the filtered stream endpoint. When used with filtered stream, this operator matches on replies to an original Post, replies in quoted Posts, and replies in Retweets. Example: from:XDevelopers is:reply
is:quoteConjunction requiredCoreReturns all Quote Tweets, also known as Posts with comments. Example: "sentiment analysis" is:quote
is:verifiedConjunction requiredCoreDeliver only Posts whose authors are verified by X. Example: #nowplaying is:verified
-is :nullcastConjunction requiredAdvancedRemoves Posts created for promotion only on ads.twitter.com that have a "source":"Twitter for Advertisers (legacy)" or "source":"Twitter for Advertisers". This operator must be negated. For more info on Nullcasted Posts, see our page on Post availability. Example: "mobile games" -is:nullcast
has:hashtagsConjunction requiredCoreMatches Posts that contain at least one hashtag. Example: from:XDevelopers -has:hashtags
has:cashtagsConjunction requiredAdvancedMatches Posts that contain a cashtag symbol (with a leading ‘character.Forexample,’ character. For example, `tag). Example: #stonks has:cashtags`
has:linksConjunction requiredCoreThis operator matches Posts which contain links and media in the Post body. Example: from:XDevelopers announcement has:links
has:mentionsConjunction requiredCoreMatches Posts that mention another X user. Example: #nowplaying has:mentions
has:mediaConjunction requiredCoreMatches Posts that contain a media object, such as a photo, GIF, or video, as determined by X. This will not match on media created with Periscope, or Posts with links to other media hosting sites. Example: (kittens OR puppies) has:media
has:imagesConjunction requiredCoreMatches Posts that contain a recognized URL to an image. Example: #meme has:images
has:videosConjunction requiredCoreMatches Posts that contain native X videos, uploaded directly to X. This will not match on videos created with Periscope, or Posts with links to other video hosting sites. Example: #icebucketchallenge has:videos
has:geoConjunction requiredAdvancedMatches Posts that have Post-specific geolocation data provided by the X user. This can be either a location in the form of a X place, with the corresponding display name, geo polygon, and other fields, or in rare cases, a geo lat-long coordinate. Note: Operators matching on place (Post geo) will only include matches from original posts. Retweets do not contain any place data. Example: recommend #paris has:geo -bakery
lang:Conjunction requiredCoreMatches Posts that have been classified by X as being of a particular language (if, and only if, the Post has been classified). It is important to note that each Post is currently only classified as being of one language, so AND’ing together multiple languages will yield no results. You can only pass a single BCP 47 language identifier per lang: operator. Note: if no language classification can be made the provided result is ‘und’ (for undefined). Example: recommend #paris lang:en
Amharic: amGerman: deMalayalam: mlSlovak: sk
Arabic: arGreek: elMaldivian: dvSlovenian: sl
Armenian: hyGujarati: guMarathi: mrSorani Kurdish: ckb
Basque: euHaitian Creole: htNepali: neSpanish: es
Bengali: bnHebrew: iwNorwegian: noSwedish: sv
Bosnian: bsHindi: hiOriya: orTagalog: tl
Bulgarian: bgLatinized Hindi: hi-LatnPanjabi: paTamil: ta
Burmese: myHungarian: huPashto: psTelugu: te
Croatian: hrIcelandic: isPersian: faThai: th
Catalan: caIndonesian: inPolish: plTibetan: bo
Czech: csItalian: itPortuguese: ptTraditional Chinese: zh-TW
Danish: daJapanese: jaRomanian: roTurkish: tr
Dutch: nlKannada: knRussian: ruUkrainian: uk
English: enKhmer: kmSerbian: srUrdu: ur
Estonian: etKorean: koSimplified Chinese: zh-CNUyghur: ug
Finnish: fiLao: loSindhi: sdVietnamese: vi
French: frLatvian: lvSinhala: siWelsh: cy
Georgian: kaLithuanian: lt

Comparing X API’s Post counts endpoints

The v2 Post counts endpoint will eventually replace the enterprise Search API’s counts endpoint. If you have code, apps, or tools that use an older version of a Post counts endpoint and are considering migrating to the newer X API v2 endpoints, then this guide is for you.

This page contains two comparison tables:

Recent Post counts comparison

The enterprise version of the Post counts endpoints allow you to pull counts for either 30 days or from the full-archive. Therefore, the v2 recent Post counts endpoint, which looks at a 7 day time period, is not a direct replacement for either of the aforementioned endpoints.

However, to help with comparisons, we will look at how the v2 recent Post counts endpoint compares to the enterprise 30-day endpoint.

The following table compares the various types of recent Post counts endpoints:

DescriptionEnterpriseX API v2
Host domainhttps://gnip-api.x.comhttps://api.x.com
Endpoint path/search/30day/accounts/:account_name/:label/counts.json/2/tweets/counts/recent
AuthenticationBasic authenticationOAuth 2.0 Bearer Token
Timestamp formatYYYYMMDDhhmmYYYY-MM-DDTHH:mm:ssZ
ISO 8601 / RFC 3339
Returns counts of Posts that are no older than31 days7 days
HTTP methods supportedGETGET
Default request rate limits20 requests per 1 sec, aggregated across search data and counts requests
The per minute rate limit will vary by partner as specified in your contract.
180 requests per 15 min per user
450 requests per 15 min per App
Supports filtering using annotations
Supports filtering using conversation_id
JSON key name for Post data arrayresultsdata
Time granularityDay, hour, or minuteDay, hour, or minute
TimezoneUTCUTC
Request parameters for selecting time periodfromDate
toDate
start_time
end_time
Request parameters for navigating by Post IDsince_id
until_id
Requires the use of credentials from a developer App associated with a project

Full-archive Post counts comparison

The following table compares the various types of full-archive search endpoints:

DescriptionEnterpriseX API v2
Host domainhttps://gnip-api.x.comhttps://api.x.com
Endpoint path/search/fullarchive/accounts/:account_name/:label/counts/2/tweets/counts/all
AuthenticationBasic authOAuth 2.0 Bearer Token
Timestamp formatYYYYMMDDHHMMYYYY-MM-DDTHH:mm:ssZ
ISO 8601 / RFC 3339
Returns Post counts that are no older thanThe full archive since March 2006The full archive since March 2006
HTTP methods supportedGET
POST
GET
Default request rate limitsThe per minute rate limit will vary by partner as specified in your contract.
20 requests per sec
300 requests per 15 min per App
1 request per 1 sec per App
GranularityDay, hour, minuteDay, hour, minute
Supports filtering using annotations
Supports filtering using conversation_id
JSON key name for Post data arrayresultsdata
Request parameters for selecting time periodfromDate
toDate
start_time
end_time
Request parameters for navigating by Post IDsince_id
until_id
JSON key name for paginationnextmeta.next_token
Request parameter for paginationnext_tokennext_token or pagination_token
TimezoneUTCUTC
Requires the use of credentials from a developer App associated with a Project that has Academic Research access

Filtering operator comparison

The two different versions (enterprise, and v2) of Post counts differ in which operators are available, and also have varying levels of operator availability within each version, which are explained below.

Enterprise

  • There are no sub-tiers of enterprise operators. All enterprise operators are available to all enterprise users.

X API v2

  • Core: These operators are available to any v2 user.
  • Advanced: These operators are only available to users that have been approved for Academic Research access.

You can learn more about each of these sets of operators in their respective guides:

Now that we understand these different operator levels within X API v2, here is the table that maps out operator availability for Post counts (note that if the cell is left blank, the operator is not available):

Enterprisev2
keywordAvailableCore
emojiAvailableCore
“exact phrase”AvailableCore
#AvailableCore
$AvailableAdvanced
@AvailableCore
from:AvailableCore
to:AvailableCore
url:AvailableCore
retweets_of:AvailableCore
context:Core
entity:Core - Only available with recent search
conversation_id:Core
place:AvailableAdvanced
place_country:AvailableAdvanced
point_radius:AvailableAdvanced
bounding_box:AvailableAdvanced
is:retweetAvailableCore
is:replyAvailableCore
is:quoteAvailableCore
is:verifiedAvailableCore
-is:nullcastAvailableAdvanced
has:hashtagsAvailableCore
has:cashtagsAvailableAdvanced
has:linksAvailableCore
has:mentionsAvailableCore
has:mediaAvailableCore
has:imagesAvailableCore
has:videosAvailableCore
has:geoAvailableAdvanced
lang:AvailableCore
list:Advanced
has:profile_geoAvailable
profile_countryAvailable
profile_localityAvailable
profile_regionAvailable
proximityAvailable

Other migration resources

X API migration hub

Check out some sample code for these endpoints

Post counts: Enterprise to X API v2

Enterprise compared to X API v2

Similarities

  • Granularity
  • Pagination
  • Timezone

Differences

  • Endpoint URLs
  • App and Project requirement
  • Available time periods
  • Response data format
  • HTTP methods
  • Request time formats
  • Request parameters
  • Filtering operators

Similarities

Granularity

While the parameter for selecting granularity of the returned data is different (bucket for the enterprise version, granularity for the v2 version), the values that you can pass with that parameter are the same, as well as the default behavior:

  • day
  • hour (default)
  • minute

Pagination

While v2 has additional pagination features (new pagination parameters that allow you to navigate using Post IDs with since_id and until_id), both enterprise and v2 allow you to paginate using time (fromDate and toDate with enterprise, and start_time and end_time for v2).

If you are using the enterprise version, you will use the next parameter to paginate, the next token field will be called next, and it will be located at the root in the response.

If you are using v2, you can use either the next_token or pagination_token parameter to paginate, and your next token will be located at meta.next_token in the response.  

Timezone

As noted in the pagination section, you can navigate different pages of data using time for both enterprise and v2. In both cases, you will be using UTC as the timezone when using these parameters.

Differences

Endpoint URLs

  • Enterprise endpoints:
    • 30 day - http://gnip-api.x.com/search/30day/accounts/:account_name/:label/counts.json
    • Full-archive - http://gnip-api.x.com/search/fullarchive/accounts/:account_name/:label/counts.json
  • X API v2 endpoints
    • Recent (7 day) - https://api.x.com/2/tweets/counts/recent
    • Full-archive - https://api.x.com/2/tweets/counts/all

App and Project requirement

The X API v2 endpoints require that you use credentials from a developer App that is associated with a Project when authenticating your requests. All X API v1.1 endpoints can use credentials from standalone Apps or Apps associated with a Project.  

Available time periods

Both the enterprise API and X API v2 offer endpoints that allow you to retrieve Post volume data for the full-archive of Posts.

However, the X API v2 does not offer a 30 day time period endpoint like the enterprise API does. Instead it offers the aforementioned full-archive, or a 7 day time period, which align with the v2 Search Posts endpoints.  

Response data format

There are some slight differences in the data format that you will receive via enterprise and X API v2:

  • Enterprise’s counts data is located within a results object, while the v2 counts data is located within a data object.
  • Enterprise’s counts fields are called timePeriod (start time) and count, while v2 breaks out the time period into a start and end field (which use a different date/time format from enterprise explained in request time formats), and renamed the count field to tweet_count.
  • The enterprise metadata includes totalCount, next, and the requestParameters object at the root level. Instead,v2 doesn’t include the requestParameters object, and moves/renames the following into a meta object that lives at the root level: total_tweet_count & next_token.  

HTTP methods

The enterprise version of the API allows you to pass the request as either a POST HTTP method with a JSON body, or a GET HTTP method with a query string.

V2 only allows you to use the GET HTTP method with a query string.  

Request time formats

The enterprise version of this endpoint uses the following date/time format in both the pagination parameters and the timePeriod response field: YYYYMMDDHHmm

The v2 endpoint uses ISO 8601/RFC 3339 date/time format in both the pagination parameters and the start and end response fields: YYYY-MM-DDTHH:mm:ssZ

Request parameters

The following is a table of the request parameters for enterprise and X API v2:

EnterpriseSearch Posts v2
queryquery
bucketgranularity
fromDate (YYMMDDHHmm)start_time (YYYY-MM-DDTHH:mm:ssZ)
toDate (YYMMDDHHmm)end_time (YYYY-MM-DDTHH:mm:ssZ)
since_id
until_id
nextnext_token and pagination_token

Filtering operators

While the operators between enterprise and X API v2 are mostly the same, there are some differences in operator availability and some new operators that were introduced to just the X API v2 version.

To see a full table of the operators that are available for X API v2, enterprise, and even premium, please visit the Post counts migration landing page.

API reference index

For a complete API reference, please select an endpoint from below.

Recent Post counts

Receive a count of Posts that match a query in the last 7 days[GET /2/tweets/counts/recent](/x-api/x-api-v2/tweets/tweet-counts#api-reference-index/get-tweets-counts-recent)

Full-archive Post counts

Only available to those with Pro and Enterprise access

Receive a count of Posts that match a query[GET /2/tweets/counts/all](/x-api/x-api-v2/tweets/tweet-counts#api-reference-index/get-tweets-counts-all)