Twitter API returns error 215, Bad Authentication Data

PhpApiTwitter

Php Problem Overview


I am trying to call following Twitter's API to get a list of followers for a user.

http://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

And I am getting this error message in response.

{
    code = 215;
    message = "Bad Authentication data";
}

I can't seem to find the documentation related to this error code. Anyone has any idea about this error?

Php Solutions


Solution 1 - Php

A very concise code without any other php file include of oauth etc. Please note to obtain following keys you need to sign up with https://dev.twitter.com and create application.

<?php
$token = 'YOUR_TOKEN';
$token_secret = 'YOUR_TOKEN_SECRET';
$consumer_key = 'CONSUMER_KEY';
$consumer_secret = 'CONSUMER_SECRET';

$host = 'api.twitter.com';
$method = 'GET';
$path = '/1.1/statuses/user_timeline.json'; // api call path

$query = array( // query parameters
    'screen_name' => 'twitterapi',
    'count' => '5'
);

$oauth = array(
    'oauth_consumer_key' => $consumer_key,
    'oauth_token' => $token,
    'oauth_nonce' => (string)mt_rand(), // a stronger nonce is recommended
    'oauth_timestamp' => time(),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_version' => '1.0'
);

$oauth = array_map("rawurlencode", $oauth); // must be encoded before sorting
$query = array_map("rawurlencode", $query);

$arr = array_merge($oauth, $query); // combine the values THEN sort

asort($arr); // secondary sort (value)
ksort($arr); // primary sort (key)

// http_build_query automatically encodes, but our parameters
// are already encoded, and must be by this point, so we undo
// the encoding step
$querystring = urldecode(http_build_query($arr, '', '&'));

$url = "https://$host$path";

// mash everything together for the text to hash
$base_string = $method."&".rawurlencode($url)."&".rawurlencode($querystring);

// same with the key
$key = rawurlencode($consumer_secret)."&".rawurlencode($token_secret);

// generate the hash
$signature = rawurlencode(base64_encode(hash_hmac('sha1', $base_string, $key, true)));

// this time we're using a normal GET query, and we're only encoding the query params
// (without the oauth params)
$url .= "?".http_build_query($query);
$url=str_replace("&amp;","&",$url); //Patch by @Frewuill

$oauth['oauth_signature'] = $signature; // don't want to abandon all that work!
ksort($oauth); // probably not necessary, but twitter's demo does it

// also not necessary, but twitter's demo does this too
function add_quotes($str) { return '"'.$str.'"'; }
$oauth = array_map("add_quotes", $oauth);

// this is the full value of the Authorization line
$auth = "OAuth " . urldecode(http_build_query($oauth, '', ', '));

// if you're doing post, you need to skip the GET building above
// and instead supply query parameters to CURLOPT_POSTFIELDS
$options = array( CURLOPT_HTTPHEADER => array("Authorization: $auth"),
                  //CURLOPT_POSTFIELDS => $postfields,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

// do our business
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$twitter_data = json_decode($json);


foreach ($twitter_data as &$value) {
   $tweetout .= preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '<a href="http://$2$3" target="_blank">$1$2$4</a>', $value->text);
   $tweetout = preg_replace("/@(\w+)/", "<a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>", $tweetout);
   $tweetout = preg_replace("/#(\w+)/", "<a href=\"http://search.twitter.com/search?q=\\1\" target=\"_blank\">#\\1</a>", $tweetout);
}

echo $tweetout;

?>

Regards

Solution 2 - Php

The only solution I've found so far is:

  • Create application in twitter developer panel

  • Authorize user with your application (or your application in user account) and save "oauth_token" and "oauth_token_secret" which Twitter gives you. Use TwitterOAuth library for this, it's pretty easy, see examples coming with library.

  • Using this tokens you can make authenticated requests on behalf of user. You can do it with the same library.

      // Arguments 1 and 2 - your application static tokens, 2 and 3 - user tokens, received from Twitter during authentification  
      $connection = new TwitterOAuth(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, $tokens['oauth_token'], $tokens['oauth_token_secret']);  
      $connection->host = 'https://api.twitter.com/1.1/'; // By default library uses API version 1.  
      $friendsJson = $connection->get('/friends/ids.json?cursor=-1&user_id=34342323');  
    

This will return you list of user's friends.

Solution 3 - Php

FOUND A SOLUTION - using the Abraham TwitterOAuth library. If you are using an older implementation, the following lines should be added after the new TwitterOAuth object is instantiated:

$connection->host = "https://api.twitter.com/1.1/";
$connection->ssl_verifypeer = TRUE;
$connection->content_type = 'application/x-www-form-urlencoded';

The first 2 lines are now documented in Abraham library Readme file, but the 3rd one is not. Also make sure that your oauth_version is still 1.0.

Here is my code for getting all user data from 'users/show' with a newly authenticated user and returning the user full name and user icon with 1.1 - the following code is implemented in the authentication callback file:

session_start();
require ('twitteroauth/twitteroauth.php');
require ('twitteroauth/config.php');

$consumer_key = '****************';
$consumer_secret = '**********************************';

$to = new TwitterOAuth($consumer_key, $consumer_secret);

$tok = $to->getRequestToken('http://exampleredirect.com?twitoa=1');

$token = $tok['oauth_token'];
$secret = $tok['oauth_token_secret'];

//save tokens to session
$_SESSION['ttok'] = $token;
$_SESSION['tsec'] = $secret;

$request_link = $to->getAuthorizeURL($token,TRUE);

header('Location: ' . $request_link);

The following code then is in the redirect after authentication and token request

if($_REQUEST['twitoa']==1){
    require ('twitteroauth/twitteroauth.php');
    require_once('twitteroauth/config.php');
    //Twitter Creds
    $consumer_key = '*****************';
    $consumer_secret = '************************************';

    $oauth_token = $_GET['oauth_token']; //ex Request vals->http://domain.com/twitter_callback.php?oauth_token=MQZFhVRAP6jjsJdTunRYPXoPFzsXXKK0mQS3SxhNXZI&oauth_verifier=A5tYHnAsbxf3DBinZ1dZEj0hPgVdQ6vvjBJYg5UdJI
    
    $ttok = $_SESSION['ttok'];
    $tsec = $_SESSION['tsec'];

    $to = new TwitterOAuth($consumer_key, $consumer_secret, $ttok, $tsec);
    $tok = $to->getAccessToken();
    $btok = $tok['oauth_token'];
    $bsec = $tok['oauth_token_secret'];
    $twit_u_id = $tok['user_id'];
    $twit_screen_name = $tok['screen_name'];

    //Twitter 1.1 DEBUG
    //print_r($tok);
    //echo '<br/><br/>';
    //print_r($to);
    //echo '<br/><br/>';
    //echo $btok . '<br/><br/>';
    //echo $bsec . '<br/><br/>';
    //echo $twit_u_id . '<br/><br/>';
    //echo $twit_screen_name . '<br/><br/>';
 
    $twit_screen_name=urlencode($twit_screen_name);
    $connection = new TwitterOAuth($consumer_key, $consumer_secret, $btok, $bsec);
    $connection->host = "https://api.twitter.com/1.1/";
    $connection->ssl_verifypeer = TRUE;
    $connection->content_type = 'application/x-www-form-urlencoded';
    $ucontent = $connection->get('users/show', array('screen_name' => $twit_screen_name));

    //echo 'connection:<br/><br/>';
    //print_r($connection);
    //echo '<br/><br/>';
    //print_r($ucontent);

    $t_user_name = $ucontent->name;
    $t_user_icon = $ucontent->profile_image_url;

    //echo $t_user_name.'<br/><br/>';
    //echo $t_user_icon.'<br/><br/>';
}

It took me way too long to figure this one out. Hope this helps someone!!

Solution 4 - Php

UPDATE: Twitter API 1 is now deprecated. Refer to above answer.

Twitter 1.1 does not work with that syntax (when I wrote this answer). Needs to be 1, not 1.1. This will work:

http://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=username

Solution 5 - Php

The answer by Gruik worked for me in the below thread.

{Excerpt | https://stackoverflow.com/questions/12677004/zend-service-twitter-make-api-v1-1-ready/16002174#16002174} > with ZF 1.12.3 the workaround is to pass consumerKey and consumerSecret in oauthOptions option, not directrly in the options.

    $options = array(
        'username' => /*...*/,
        'accessToken' => /*...*/,
        'oauthOptions' => array(
            'consumerKey' => /*...*/,
            'consumerSecret' => /*...*/,
        )
    );

Solution 6 - Php

The url with /1.1/ in it is correct, it is the new Twitter API Version 1.1.

But you need an application and authorize your application (and the user) using oAuth.

Read more about this on the Twitter Developers documentation site :)

Solution 7 - Php

You need to send customerKey and customerSecret to Zend_Service_Twitter

$twitter = new Zend_Service_Twitter(array(
				'consumerKey' => $this->consumer_key,
				'consumerSecret' => $this->consumer_secret,
				'username' => $user->screenName,
				'accessToken' => unserialize($user->token)
));

Solution 8 - Php

After two days of research I finally found that to access s.o. public tweets you just need any application credentials, and not that particular user ones. So if you are developing for a client, you don't have to ask them to do anything.

To use the new Twitter API 1.1 you need two things:

First, you can (actually have to) create an application with your own credentials and then get the Access token (OAUTH_TOKEN) and Access token secret (OAUTH_TOKEN_SECRET) from the "Your access token" section. Then you supply them in the constructor for the new TwitterOAuth object. Now you can access anyone public tweets.

$connection = new TwitterOAuth( CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET );

$connection->host = "https://api.twitter.com/1.1/"; // change the default
$connection->ssl_verifypeer = TRUE;
$connection->content_type = 'application/x-www-form-urlencoded';

$tweets = $connection->get('http://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.$username.'&count='.$count);

Actually I think this is what Pavel has suggested also, but it is not so obvious from his answer.

Hope this saves someone else those two days :)

Solution 9 - Php

This might help someone who use Zend_Oauth_Client to work with twitter api. This working config:

$accessToken = new Zend_Oauth_Token_Access();
$accessToken->setToken('accessToken');
$accessToken->setTokenSecret('accessTokenSecret');

$client = $accessToken->getHttpClient(array(
    'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER,
    'version' => '1.0', // it was 1.1 and I got 215 error.
    'signatureMethod' => 'HMAC-SHA1',
    'consumerKey' => 'foo',
    'consumerSecret' => 'bar',
    'requestTokenUrl' => 'https://api.twitter.com/oauth/request_token',
    'authorizeUrl' => 'https://api.twitter.com/oauth/authorize',
    'accessTokenUrl' => 'https://api.twitter.com/oauth/access_token',
    'timeout' => 30
));

It look like twitter api 1.0 allows oauth version to be 1.1 and 1.0, where twitter api 1.1 require only oauth version to be 1.0.

P.S We do not use Zend_Service_Twitter as it does not allow send custom params on status update.

Solution 10 - Php

Be sure that you have read AND write access for application in twitter

Solution 11 - Php

I'm using HybridAuth and was running into this error connecting to Twitter. I tracked it down to (me) sending Twitter an incorrectly cased request type (get/post instead of GET/POST).

This would cause a 215:

$call = '/search/tweets.json';
$call_type = 'get';
$call_args = array(
	'q'           => 'pancakes',
	'count'       => 5,
);
$response = $provider_api->api( $call, $call_type, $call_args );

This would not:

$call = '/search/tweets.json';
$call_type = 'GET';
$call_args = array(
	'q'           => 'pancakes',
	'count'       => 5,
);
$response = $provider_api->api( $call, $call_type, $call_args );

Side note: In the case of HybridAuth the following also would not (because HA internally provides the correctly-cased value for the request type):

$call = '/search/tweets.json';
$call_args = array(
	'q'           => 'pancakes',
	'count'       => 5,
);
$response = $providers['Twitter']->get( $call, $call_args );

Solution 12 - Php

I was facing the same problem all the time the only solution I figurae out is typing CONSUMER_KEY and CONSUMER_SECRET directly to new TwitterOAuth class defination .

$connection = new TwitterOAuth(  "MY_CK" , "MY_CS"  );

Don't use variable or statics on this and see if the issue sloved .

Solution 13 - Php

Here first every one need to use oauth2/token api then use followers/list api.
Other wise you will get this error. Because followers/list api requires Authentication.

In swift (for mobile app) me also got the same problem.

If you want to know the api's and it's parameters follow this link , https://stackoverflow.com/questions/54807221/get-twitter-friends-list-in-swift/54838712#54838712

Solution 14 - Php

I know that this is old but yesterday I faced the same issue when calling this URL using C# and the HttpClient class with the Bearer authentication token:

http://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

It turns out that the solution for me was to use HTTPS instead of HTTP. So my URL would look like this:

https://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

So here is a snippet of my code:

            using (var client = new HttpClient())
			{
				client.BaseAddress = new Uri("https://api.twitter.com/1.1/");
				client.DefaultRequestHeaders.Accept.Clear();
				client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
				client.DefaultRequestHeaders.Add("Authorization", "Bearer **** YOUR BEARER TOKEN GOES HERE ****");

				var response = client.GetAsync("statuses/user_timeline.json?count=10&screen_name=username").Result;
				if (!response.IsSuccessStatusCode)
				{
					return result;
				}
				var items = response.Content.ReadAsAsync<IEnumerable<dynamic>>().Result;
				foreach (dynamic item in items)
				{
					//Do the needful
				}
			}

Solution 15 - Php

Try this twitter API explorer, you can sign in as a developer and query whatever you want.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDip DhinganiView Question on Stackoverflow
Solution 1 - PhpA Bright WorkerView Answer on Stackoverflow
Solution 2 - PhpPavelView Answer on Stackoverflow
Solution 3 - PhpDante CullariView Answer on Stackoverflow
Solution 4 - PhpchristopherView Answer on Stackoverflow
Solution 5 - PhpJonathan HaarView Answer on Stackoverflow
Solution 6 - Phpspiele_rView Answer on Stackoverflow
Solution 7 - PhpJuan de ParrasView Answer on Stackoverflow
Solution 8 - PhpnobugView Answer on Stackoverflow
Solution 9 - PhpMaksim KotlyarView Answer on Stackoverflow
Solution 10 - PhpVictorView Answer on Stackoverflow
Solution 11 - PhpSkrivenerView Answer on Stackoverflow
Solution 12 - PhpSalemView Answer on Stackoverflow
Solution 13 - PhpNareshView Answer on Stackoverflow
Solution 14 - PhpalejosoftView Answer on Stackoverflow
Solution 15 - PhpethanjyxView Answer on Stackoverflow