Tech Note: A PHP Function to Properly Calculate the Length of a Tweet Before Sending It
As everyone who uses Twitter knows, there’s a limit of 140 characters per tweet. For Twitter API programmers like me, this means your code has to make sure the tweet you’re about to send is not longer than 140 characters, or Twitter will smack you on the knuckles with a ruler and send back the dreaded error message:
Error: 403 - Status is over 140 characters
So what’s the problem, you ask? Just get the length of the tweet you’re proposing to send and make sure it isn’t over 140 characters. Easy, right?
Well, it used to be this easy, but then Twitter started automatically running all links in tweets through their own custom URL shortener (t.co) — even if they’re already shortened with another service.
(Note: when you look at a tweet on Twitter, you won’t necessarily see the “t.co” URL, either; Twitter automatically expands these links when it displays a tweet. But it’s stored internally as a “t.co” URL.)
This change made correctly calculating the length much more complex; now your code has to scan the tweet text to find URLs, and adjust the overall length to account for what happens when Twitter’s URL shortener does its thing.
If you’re doing this calculating in Javascript, you’re in luck; there’s an official Twitter text processing library for Javascript that includes a method called getTweetLength().
But if you need to calculate the length in a PHP script, you’re not so lucky. There is a PHP version of the twitter-text library, but the latest version doesn’t have a getTweetLength() function, alas.
Which brings us to the point of this post: my version of getTweetLength() for PHP (implemented in our “Now Playing” auto-tweets).
This code uses the PHP twitter-text scripts (linked above), so you’ll need to first upload them to a convenient place in your server’s PHP include path.
A summary of how it works: it’s called with two parameters, the tweet text string, and a true/false flag called $gotImage which indicates whether the tweet will have an image attached. It sets up variables for the t.co lengths of http and https URLs, and the length of an image URL. Then it calls the Twitter_Extractor class (as a singleton) to parse the tweet with a whole bunch of magical regular expressions, and return all the data about it in an associative array called $urlData. (If you run tests/example.php from the PHP twitter-text package, you’ll see the structure of this array.)
Then the code gets the “raw” length of the tweet in the variable $tweetLength (oddly enough), and goes into a loop for each URL found in the tweet, first subtracting the raw length of the URL from $tweetLength, then adding back the length of the t.co-shortened URL. It checks to see if the original URL was an http or https link, and adjusts accordingly.
When the loop finishes, it checks to see if the tweet has an image, and adds the length of that URL (which will also end up shortened with t.co). In this example, we’re just assuming there’s no image, so we pass FALSE to the function.
Note: Twitter recommends that you use their API to check the default lengths of shortened URLs on a periodic basis, because they might change.
require_once 'twitter-text/Extractor.php';
function getTweetLength($tweet, $gotImage) {
$tcoLengthHttp = 22;
$tcoLengthHttps = 23;
$twitterPicLength = 22;
$urlData = Twitter_Extractor::create($tweet)->extract();
$tweetLength = mb_strlen($tweet);
foreach ($urlData['urls_with_indices'] as $url) {
$tweetLength -= mb_strlen($url['url']);
$tweetLength += mb_stristr($url['url'], 'https') === 0
? $tcoLengthHttps
: $tcoLengthHttp;
}
if ($gotImage) $tweetLength += $twitterPicLength;
return $tweetLength;
}
$tweet = '#NowPlaying Fountains of Wayne > Fountains of Wayne > Leave the Biker http://lgf.bz/wuVVAm';
if (getTweetLength($tweet, FALSE) > 140) {
echo 'Error! The tweet is longer than 140 characters.';
} else {
tweetThisMutha($tweet);
}