Interested in exploring Labs?
The endpoints we release in Labs are previews of tools that may be released more broadly in the future, but will likely undergo changes before then. We encourage you to take that into consideration as you explore. Before getting started, please read more about Twitter Developer Labs.

Still using v1?
This page documents the current version of this endpoints, however you can still reference the previous version. You should also check out our version migration guide and review our changelog.
 

Getting started with the Labs recent search endpoint

The GET /tweets/search endpoint provides developers with public Tweet data for available Tweets matching a provided search query. The information returned by the endpoint includes Tweet objects in JSON format. An array of matching Tweet objects contains public Twitter account metadata such as id, text, created_at, lang, and more. To learn more about possible data returned in the Tweet payload, check out the API reference response object data dictionary or full set of options for the fields parameter.

In the following quick start guide, we will search Tweets that match a query and specify a set of fields desired for the response, including one expansion for media.

There are a few steps required before sending requests. In order to access the GET /tweets/search endpoint, you will need the following:

Authentication

All the endpoints in this preview are authenticated using OAuth 2.0 Bearer Token (also known as application-only authentication). This means you will need to generate a Bearer token, and pass this token in all of your requests. Once configured, our Postman collection will handle the generation of a Bearer Token for you. Other clients like curl and Insomnia will require you to generate a token manually.
 

REST Client

REST applications such as Postman can be used for organizing, testing, and debugging HTTP requests.

We have compiled a collection of example requests to all Twitter Developer Labs endpoints, including recent search. Postman provides a user-interfaces for managing authentication, setting request headers, working with request parameters, and examining response JSON.

You can get started with a Labs collection by reading our "Getting started with Postman" tutorial and clicking on the following button:

 

Accessing the Recent Search API

The example requests below search for Tweets from @TwitterDev that also have media.

The following code examples should help you starting making search requests from code. Below you will find examples in Python, Ruby, Node.js, and Java.

These examples illustrate the basic mechanics of the endpoint, making an authenticated request and displaying the response, but are not well suited for real-world use. One reason is that they work directly with hard-coded Consumer API Keys and Secrets, instead of loading credential tokens from another resource. Another reason is that they make a single request and stop, rather than using pagination to collect all of the matching Tweets.

These and other scripts are available in our Labs Sample Code repository.

  • cURL
  • Python 3
  • Ruby
  • JavaScript (Node.js)
  • Java
  • R

cURL is a command-line tool for getting or sending files using the URL syntax.
 

Make sure the app is enabled for Recent Search.
 

Copy the following cURL request into your command line after making changes to the following:
 

Replace <BEARER_TOKEN> with your own, which will look something like AAAAAAAAAAAA0%2EUifi76ZC9Ub0wnsg3

  curl -X GET -H "Authorization: Bearer <BEARER_TOKEN>"  \
"https://api.twitter.com/labs/2/tweets/search?tweet.fields=created_at,author_id,lang&query=from%3Atwitterdev%20has%3Amedia"

This Python example takes your app's Consumer Key and Secret, generates a Bearer Token via the Twitter platform, then makes a single Labs recent search request using OAuth 2.0 Bearer Token authentication.

 

To use the following script, make sure your system is using Python 3 and copy in your Twitter developer app's Consumer API Key and Secret. While this script is OK for making some practice requests, it hard-codes keys and does not implement any form of pagination. 

 

We have an additional Python script on our GitHub page, which reads credentials from an .env file, implements pagination, and can limit the number of requests made:

  import json
import urllib.parse
import requests
from requests.auth import AuthBase

# Fill these in. Generate tokens at https://developer.twitter.com/en/apps. 
CONSUMER_KEY = ''
CONSUMER_SECRET = ''

query = urllib.parse.quote("from:TwitterDev has:media")

url = f"https://api.twitter.com/labs/2/tweets/search?query={query}"

headers = {
    "Accept-Encoding": "gzip"
}

# Generates a bearer token with consumer key and secret via https://api.twitter.com/oauth2/token.
class BearerTokenAuth(AuthBase):
    def __init__(self, consumer_key, consumer_secret):
        self.bearer_token_url = "https://api.twitter.com/oauth2/token"
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.bearer_token = self.get_bearer_token()

    def get_bearer_token(self):
        response = requests.post(
            self.bearer_token_url,
            auth=(self.consumer_key, self.consumer_secret),
            data={'grant_type': 'client_credentials'},
            headers={'User-Agent': 'LabsRecentSearchQuickStartPython'})

        if response.status_code is not 200:
            raise Exception("Cannot get a Bearer token (HTTP %d): %s" % (response.status_code, response.text))

        body = response.json()
        return body['access_token']

    def __call__(self, r):
        r.headers['Authorization'] = f"Bearer %s" % self.bearer_token
        r.headers['User-Agent'] = 'LabsResearchSearchQuickStartPython'
        return r

# Script starts here.

#Create Bearer Token for authenticating with recent search.
bearer_token = BearerTokenAuth(CONSUMER_KEY, CONSUMER_SECRET)

#Make a GET request to the Labs recent search endpoint.
response = requests.get(url, auth=bearer_token, headers = headers)

if response.status_code is not 200:
    raise Exception(f"Request reurned an error: %s" % (response.status_code, response.text))

#Display the returned Tweet JSON.
parsed = json.loads(response.text)
pretty_print = json.dumps(parsed, indent=2, sort_keys=True)
print (pretty_print)

This Ruby example takes your app's consumer key and secret, generates a Bearer Token via the Twitter platform, then makes a Labs recent search request using OAuth 2.0 Bearer Token authentication
 

To use the following script, copy in your Twitter developer app's Consumer Key and Secret tokens and run it with Ruby. While the following script is OK for making some practice requests, it hard-codes keys and does not implement any form of pagination. 
 

We have an additional Ruby script on our GitHub page, which reads credentials from an .env file, implements pagination, and can limit the number of requests made:

  require "net/https"
require "uri"
require 'base64'
require 'json'

#Quote your Twitter App consumer keys here.
#See [THIS CODE] for a better way to handle and configure your keys.
CONSUMER_KEY = "" # Add your API key here
CONSUMER_SECRET = "" # Add your API secret key here

@search_url = "https://api.twitter.com/labs/2/tweets/search"
query = 'from:twitterdev has:media'

options = {"query" => query}

def bearer_token(consumer_key, consumer_secret)
# Generates a Bearer Token using your Twitter App's consumer key and secret.
# Calls the Twitter URL below and returns the Bearer Token.
  bearer_token_url = "https://api.twitter.com/oauth2/token"

  return @bearer_token unless @bearer_token.nil?

  credentials = Base64.encode64("#{consumer_key}:#{consumer_secret}").gsub("\n", "")

  uri = URI(bearer_token_url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  request = Net::HTTP::Post.new(uri.path)
  request.body =  "grant_type=client_credentials"
  request['Authorization'] = "Basic #{credentials}"
  request['User-Agent'] = "RecentSearchQuickStartRuby"

  response = http.request(request)

  body = JSON.parse(response.body)

  body['access_token']

end

def make_request(key, secret, query)

  uri = URI(@search_url)

  options = {}
  options['query'] = query
  options['max_results'] = 10
  #options['start_time'] = nil
  #options['end_time'] = nil

  uri.query = URI.encode_www_form(options)

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  request = Net::HTTP::Get.new(uri.request_uri)
  request['Authorization'] = "Bearer #{bearer_token(key,secret)}"
  request['User-Agent'] = "RecentSearchQuickStartRuby"

  response = http.request(request)

  return response
end

response = make_request(CONSUMER_KEY, CONSUMER_SECRET, query)

puts JSON.pretty_generate(JSON.parse(response.body))

This below Node.js example takes your App's Consumer Key and Secret, generates a Bearer Token via the Twitter platform, then makes a Labs recent search request using OAuth 2.0 Bearer Token authentication.

To use the following script, copy in your Twitter developer app's Consumer Key and Secret tokens and run it with Node. While the following script is OK for making some practice requests, it hard-codes keys and does not implement any form of pagination. 

  const https = require('https');
const request = require('request');
const util = require('util');

const get = util.promisify(request.get);
const post = util.promisify(request.post);

const consumer_key = ''; // Add your API key here
const consumer_secret = ''; // Add your API secret key here

const bearerTokenURL = new URL('https://api.twitter.com/oauth2/token');
const searchURL = new URL('https://api.twitter.com/labs/2/tweets/search');

async function bearerToken (auth) {
  const requestConfig = {
    url: bearerTokenURL,
    auth: {
      user: consumer_key,
      pass: consumer_secret,
    },
    form: {
      grant_type: 'client_credentials',
    },
  };

  const response = await post(requestConfig);
  return JSON.parse(response.body).access_token;
}

(async () => {
  let token;
  const query = 'from:twitterdev has:media';
  const maxResults = 10;

  try {
    // Exchange your credentials for a Bearer token
    token = await bearerToken({consumer_key, consumer_secret});
  } catch (e) {
    console.error(`Could not generate a Bearer token. Please check that your credentials are correct and that the Filtered Stream preview is enabled in your Labs dashboard. (${e})`);
    process.exit(-1);
  }

  const requestConfig = {
    url: searchURL,
    qs: {
      query: query,
      max_results: maxResults,
    },
    auth: {
      bearer: token,
    },
    headers: {
      'User-Agent': 'LabsRecentSearchQuickStartJS',
    },
    json: true,
  };

  try {
    const res = await get(requestConfig);  
    console.log(res.statusCode);
    console.log(res);
    if (res.statusCode !== 200) {
      throw new Error(res.json);
      return;
    }

    console.log(res.json);
  } catch (e) {
    console.error(`Could not get search results. An error occurred: ${e}`);
    process.exit(-1);
  }
})();

This Java example takes your Twitter developer app's Consumer Key and Secret, generates a Bearer Token via the Twitter platform, then makes a single Labs recent search request using OAuth 2.0 Bearer Token authentication

 

To use the following script, copy in your Twitter developer app's Consumer Key and Secret tokens and run it.

 

While this script is OK for making some practice requests, it hard-codes keys and does not implement any form of pagination. 

 

  /*
 * Sample code to demonstrate the use of the Labs recent Search endpoint
 * */
public class RecentSearchDemo {

    //FIXME Replace the keys below with your own keys and secret
    private static final String API_KEY = "";
    private static final String API_SECRET = "";

    public static void main(String args[]) throws IOException, URISyntaxException {
        //Replace the search term with a term of your choice
        String response = search("(Labs Search Twitter) OR from:TwitterDev OR from:SnowBotDev OR from:DailyNASA");
        System.out.println(response);
    }

    /*
    * This method calls the recent search endpoint with a the search term passed to it as a query parameter
    * */
    private static String search(String searchString) throws IOException, URISyntaxException {
        String searchResponse = null;

        HttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setCookieSpec(CookieSpecs.STANDARD).build())
                .build();

        URIBuilder uriBuilder = new URIBuilder("https://api.twitter.com/labs/2/tweets/search");
        ArrayList<NameValuePair> queryParameters;
        queryParameters = new ArrayList<>();
        queryParameters.add(new BasicNameValuePair("query", searchString));
        uriBuilder.addParameters(queryParameters);

        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.setHeader("Authorization", String.format("Bearer %s", getAccessToken()));
        httpGet.setHeader("Content-Type", "application/json");
        httpGet.setHeader("User-Agent", "LabsRecentSearchQuickStartJava");

        HttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if (null != entity) {
            searchResponse = EntityUtils.toString(entity, "UTF-8");
        }
        return searchResponse;
    }

    /*
     * Helper method that generates bearer token by calling the /oauth2/token endpoint
     * */
    private static String getAccessToken() throws IOException, URISyntaxException {
        String accessToken = null;

        HttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setCookieSpec(CookieSpecs.STANDARD).build())
                .build();

        URIBuilder uriBuilder = new URIBuilder("https://api.twitter.com/oauth2/token");
        ArrayList<NameValuePair> postParameters;
        postParameters = new ArrayList<>();
        postParameters.add(new BasicNameValuePair("grant_type", "client_credentials"));
        uriBuilder.addParameters(postParameters);

        HttpPost httpPost = new HttpPost(uriBuilder.build());
        httpPost.setHeader("Authorization", String.format("Basic %s", getBase64EncodedString()));
        httpPost.setHeader("Content-Type", "application/json");

        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();

        if (null != entity) {
            try (InputStream inputStream = entity.getContent()) {
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> jsonMap = mapper.readValue(inputStream, Map.class);
                accessToken = jsonMap.get("access_token").toString();
            }
        }
        return accessToken;
    }

    /*
     * Helper method that generates the Base64 encoded string to be used to obtain bearer token
     *
     * */
    private static String getBase64EncodedString() {
        String s = String.format("%s:%s", API_KEY, API_SECRET);
        return Base64.getEncoder().encodeToString(s.getBytes(StandardCharsets.UTF_8));
    }
}

This R example takes your Twitter developer app's Consumer Key and Secret, generates a Bearer Token via the Twitter platform, then makes a single Labs recent search request using OAuth 2.0 Bearer Token authentication.

 

To use the following script, copy in your Twitter developer app's Consumer Key and Secret tokens and run it.

 

  library(httr)
library(jsonlite)
library(caTools)
library(dplyr)

# Replace the keys below from your Twitter app from https://developer.twitter.com/en/apps
api_key <- 'REPLACE_API_KEY'
api_secret <- 'REPLACE_API_SECRET'

encoded_keys <- base64encode(sprintf('%s:%s', api_key, api_secret))

access_token_request <-
  POST(url = 'https://api.twitter.com/oauth2/token',
       body = 'grant_type=client_credentials',
       add_headers
       (
         .headers = c(
           'Authorization' = sprintf('Basic %s', encoded_keys),
           'Content-Type' = 'application/x-www-form-urlencoded'
         )
       ))

access_token_body <- content(access_token_request, as = 'parsed')
access_token <- access_token_body$access_token

search_term <- 'snow -is:retweet lang:en'
recent_search_request <-
  GET(
    url = 'https://api.twitter.com/labs/2/tweets/search',
    query = list(query = search_term, max_results = 50),
    add_headers
    (
      .headers = c(
        'Authorization' = sprintf('Bearer %s', access_token),
        'Content-Type' = 'application/json'
      )
    )
  )

recent_search_body <-
  content(
    recent_search_request,
    as = 'parsed',
    type = 'application/json',
    simplifyDataFrame = TRUE
  )

View(recent_search_body$data)

Recent Search response:

The response for Recent Search request shown above will look like the JSON below:

{
  "data": [
    {
      "author_id": "2244994945",
      "created_at": "2020-02-12T17:09:56.000Z",
      "id": "1227640996038684673",
      "lang": "en",
      "text": "Doctors: Googling stuff online does not make you a doctor\n\nDevelopers: https://t.co/mrju5ypPkb"
    },
    {
      "author_id": "2244994945",
      "created_at": "2020-02-07T22:48:32.000Z",
      "id": "1225914265946730497",
      "lang": "en",
      "text": "RT @usman4all: Join us tomorrow for #TapIntoTwitterLafia Q1 Meetup of the year tomorrow. #TapIntoTwitter\nCc: @TwitterDev @compston @lvhcolo…"
    }
  ],
  "meta": {
    "newest_id": "1227640996038684673",
    "oldest_id": "1225914265946730497",
    "result_count": 2
  }
}

 


 

Additional resources