<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>twitpic &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/twitpic/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Tue, 26 Aug 2025 06:50:09 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>twitpic &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Exporting TwitPic Images - Python]]></title>
		<link>https://shkspr.mobi/blog/2013/08/exporting-twitpic-images-python/</link>
					<comments>https://shkspr.mobi/blog/2013/08/exporting-twitpic-images-python/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 26 Aug 2013 11:00:01 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[twitpic]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">http://shkspr.mobi/blog/?p=8674</guid>

					<description><![CDATA[As part of my quest to ensure I have a reasonable backup of all my social media data, I&#039;ve been investigating ho easy it is to export photos from TwitPic.  I&#039;ve been using TwitPic since 2008 and have uploaded 1,200 images there.  There&#039;s no official export function for TwitPic.  The services which used to exist relied on their RSS feeds - which have since been killed off.  This little Python…]]></description>
										<content:encoded><![CDATA[<p>As part of my quest to ensure I have a reasonable backup of all my social media data, I've been investigating ho easy it is to export photos from TwitPic.</p>

<p>I've been using TwitPic since 2008 and have uploaded 1,200 images there.</p>

<p>There's no official export function for TwitPic.  The services which used to exist relied on their RSS feeds - which have since been killed off.</p>

<p>This little Python script uses some <em>undocumented</em> APIs to grab all your images, save them in a directory, and make sure they have the correct timestamp.</p>

<p>Firstly, the documented bit.  It's possible to make an <a href="https://web.archive.org/web/20130822085313/http://dev.twitpic.com/docs/2/users_show">unauthenticated API call to get the most recent 20 images any user has uploaded</a>.</p>

<pre>https://api.twitpic.com/2/users/show.json?username=edent&amp;page=1</pre>

<p>Obviously, use your own username in place of mine!</p>

<p>You can increment the page number, to get each page.  Using the "photo_count" property, you should be able to work out how many pages you will need to request in order to grab all the photos.  Remember to round up to the nearest integer.</p>

<p>Next, we have the undocumented API call.  It's possible to <a href="https://web.archive.org/web/20130906081837/https://dev.twitpic.com/docs/thumbnails/">request the thumbnail of an image</a> with a simple API call:</p>

<pre>https://twitpic.com/show/thumb/d834ni</pre>

<p>To grab the full image, simply change "thumb" to "full":</p>

<pre>http://twitpic.com/show/full/d834ni</pre>

<h2 id="deficiencies"><a href="https://shkspr.mobi/blog/2013/08/exporting-twitpic-images-python/#deficiencies">Deficiencies</a></h2>

<p>Sadly, the TwitPic images don't retain their original EXIF metadata - so there's no way of seeing where the photo was take, what camera was used, etc.</p>

<p>In fact, original images are not preserved at all. None seem to be larger than 800*600 - even though the API "helpfully" tells you what their original full resolution was.</p>

<p>My code is a quick sketch in Python. It could be made to run in parallel as it takes quite a while to download all the images - even though the total file size was only 100MB.</p>

<p>It has only been tested on Linux, so some things may need to change if you're on another OS.  Specifically, this code strips out "/" from the file name - other computers may need other special characters replaced.</p>

<p>My code also assumes you have 100 pages or fewer of pictures to download.</p>

<p>On the plus side, it does make sure that the file names won't be too long for your file system and that any HTML entities are correctly decoded.</p>

<p>Enjoy!</p>

<h2 id="code"><a href="https://shkspr.mobi/blog/2013/08/exporting-twitpic-images-python/#code">Code</a></h2>

<pre lang="python">import urllib
import urllib2
import json
import collections
import HTMLParser
import time
import os

#   Create a parser for HTML entities
h = HTMLParser.HTMLParser()

#   Maximum filename length
#   Last 4 characters will be .jpg or .png etc
max_length = os.statvfs('.').f_namemax - 4

#   Target Page
twitpic_api = "https://api.twitpic.com/2/users/show.json?username=YOURNAMEHERE&amp;page="

#   Get the data about the target page
for page in range(0, 100):
    print page
    twitpic_data = json.load(urllib2.urlopen(twitpic_api + str(page)))

    #   Get the info about each image on the page
    twitpic_images = twitpic_data["images"]

    for item in twitpic_images:
        twitpic_id = item['short_id']
        twitpic_title = item["message"]
        #   Replace / (which can't be used in a file name) with a similar looking character
        twitpic_title = twitpic_title.replace('/', u'u2044')
        twitpic_title = twitpic_title[:max_length]
        twitpic_file_type = item["type"]
        twitpic_time = time.mktime(time.strptime(item["timestamp"], "%Y-%m-%d %H:%M:%S"))
        twitpic_file_url = "https://twitpic.com/show/full/"+twitpic_id
        twitpic_file_name = h.unescape(twitpic_title) + "." + twitpic_file_type

        #   Save the file
        urllib.urlretrieve (twitpic_file_url, twitpic_file_name)
        #   Set the file time
        os.utime(twitpic_file_name,(twitpic_time, twitpic_time))

</pre>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=8674&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2013/08/exporting-twitpic-images-python/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[HOWTO: Twitpic and OAuth]]></title>
		<link>https://shkspr.mobi/blog/2010/05/howto-twitpic-and-oauth/</link>
					<comments>https://shkspr.mobi/blog/2010/05/howto-twitpic-and-oauth/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 31 May 2010 17:07:29 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[dabr]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[twitpic]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">http://shkspr.mobi/blog/?p=2084</guid>

					<description><![CDATA[I am no longer confused!  Here is a quick tutorial in how to post images to Twitpic and Twitter when using OAuth.  I&#039;m indebted to Steve Corona of Twitpic, for his help with this.  You can see the full code on Dabr&#039;s Google Code page.  First of all, you&#039;ll need to have enabled OAuth for your Twitter client.  I use Abraham&#039;s excellent OAuth libraries for PHP.  This tutorial assumes you already…]]></description>
										<content:encoded><![CDATA[<p>I am no longer <a href="https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck">confused</a>!  Here is a quick tutorial in how to post images to Twitpic and Twitter when using OAuth.  I'm indebted to <a href="http://twitter.com/stevencorona">Steve Corona of Twitpic</a>, for his help with this.</p>

<p>You can see the full code on <a href="http://code.google.com/p/dabr/source/detail?r=318">Dabr's Google Code page</a>.</p>

<p>First of all, you'll need to have enabled OAuth for your Twitter client.  I use Abraham's excellent <a href="http://github.com/abraham/twitteroauth/tree/master/twitteroauth/">OAuth libraries for PHP</a>.</p>

<p>This tutorial assumes you already have OAuth working.  I'll attempt to explain what I'm doing as I go along - but the code should be pretty readable.</p>

<p>Start by reading the <a href="https://web.archive.org/web/20100522065016/http://dev.twitpic.com/docs/2/upload/">Twitpic API documentation</a>.  You will also need to register for an API key - this only takes a few seconds.</p>

<p>We start by setting CURL's headers to those required by Twitpic</p>

<pre><code class="language-php">//Has the user submitted an image and message?
if ($_POST['message'])
{
    $twitpicURL = 'http://api.twitpic.com/2/upload.json';

    //Set the initial headers
    $header = array(
                            'X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json',
                            'X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/"'
                        );
</code></pre>

<p>Next, we create the OAuth credentials that we need.  Essentially, we're signing a URL request. We then pass that on to Twitpic and they verify it with Twitter.  We <em>never</em> pass our OAUTH_CONSUMER_SECRET - so Twitpic can't impersonate us.</p>

<pre><code class="language-php">    //Using Abraham's OAuth library
    require_once('OAuth.php');

    // instantiating OAuth customer
    $consumer = new OAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET);

    // instantiating signer
    $sha1_method = new OAuthSignatureMethod_HMAC_SHA1();

    // user's token
    list($oauth_token, $oauth_token_secret) = explode('|', $GLOBALS['user']['password']);
    $token = new OAuthConsumer($oauth_token, $oauth_token_secret);

    // Generate all the OAuth parameters needed
    $signingURL = 'https://api.twitter.com/1/account/verify_credentials.json';

    $request = OAuthRequest::from_consumer_and_token($consumer, $token, 'GET', $signingURL, array());

    $request-&gt;sign_request($sha1_method, $consumer, $token);
</code></pre>

<p>We add these generated credentials into the header.</p>

<pre><code class="language-php">    $header[1] .= ", oauth_consumer_key=\"" . $request-&gt;get_parameter('oauth_consumer_key') ."\"";
    $header[1] .= ", oauth_signature_method=\"" . $request-&gt;get_parameter('oauth_signature_method') ."\"";
    $header[1] .= ", oauth_token=\"" . $request-&gt;get_parameter('oauth_token') ."\"";
    $header[1] .= ", oauth_timestamp=\"" . $request-&gt;get_parameter('oauth_timestamp') ."\"";
    $header[1] .= ", oauth_nonce=\"" . $request-&gt;get_parameter('oauth_nonce') ."\"";
    $header[1] .= ", oauth_version=\"" . $request-&gt;get_parameter('oauth_version') ."\"";
    $header[1] .= ", oauth_signature=\"" . urlencode($request-&gt;get_parameter('oauth_signature')) ."\"";
</code></pre>

<p>Add everything into CURL</p>

<pre><code class="language-php">    //open connection
    $ch = curl_init();

    //Set paramaters
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    //set the url, number of POST vars, POST data
    curl_setopt($ch,CURLOPT_URL,$twitpicURL);
</code></pre>

<p>The data we send to Twitpic (message text, image and key) have to go via POST.</p>

<pre><code class="language-php">    //TwitPic requires the data to be sent as POST
    $media_data = array(
                            'media' =&gt; '@'.$_FILES['media']['tmp_name'],
                          'message' =&gt; ' ' . stripslashes($_POST['message']), //A space is needed because twitpic b0rks if first char is an @
                          'key'=&gt;TWITPIC_API_KEY
                        );

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$media_data);
</code></pre>

<p>All done, we now send the data to Twitpic.</p>

<pre><code class="language-php">    //execute post
    $result = curl_exec($ch);
    $response_info=curl_getinfo($ch);

    //close connection
    curl_close($ch);
</code></pre>

<p>If this has worked, Twitpic will pass back the URL of the image we posted.  We then need to post the entire message to Twitter ourselves (Twitpic can't do it for us).</p>

<pre><code class="language-php">    if ($response_info['http_code'] == 200) //Success
    {
        //Decode the response
        $json = json_decode($result);
        $id = $json-&gt;id;
        $twitpicURL = $json-&gt;url;
        $text = $json-&gt;text;
        $message = trim($text) . " " . $twitpicURL;
</code></pre>

<p>This next part is specific to Dabr - your client may post things differently.</p>

<pre><code class="language-php">        //Send the user's message to twitter
        $request = API_URL.'statuses/update.json';

        $post_data = array('source' =&gt; 'dabr', 'status' =&gt; $message);
        $status = twitter_process($request, $post_data);

        //Back to the timeline
        twitter_refresh("twitpic/confirm/$id");
    }
</code></pre>

<p>If it didn't work, Twitpic will tell us why.</p>

<pre><code class="language-php">    else
    {
        $content = "&lt;p&gt;Twitpic upload failed. No idea why!&lt;/p&gt;";
        $json = json_decode($result);
        $content .= "&lt;br /&gt;&lt;b&gt;message&lt;/b&gt; " . urlencode($_POST['message']);
        $content .= "&lt;br /&gt;&lt;b&gt;json&lt;/b&gt; " . print_r($json);
        $content .= "&lt;br /&gt;&lt;b&gt;Response&lt;/b&gt; " . print_r($response_info);
        $content .= "&lt;br /&gt;&lt;b&gt;header&lt;/b&gt; " . print_r($header);
        $content .= "&lt;br /&gt;&lt;b&gt;media_data&lt;/b&gt; " . print_r($media_data);
        $content .= "&lt;br /&gt;&lt;b&gt;URL was&lt;/b&gt; " . $twitpicURL;
        $content .= "&lt;br /&gt;&lt;b&gt;File uploaded was&lt;/b&gt; " . $_FILES['media']['tmp_name'];
    }
}
</code></pre>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=2084&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2010/05/howto-twitpic-and-oauth/feed/</wfw:commentRss>
			<slash:comments>25</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Twitpic OAuth - I'm Stuck]]></title>
		<link>https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/</link>
					<comments>https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 23 May 2010 20:15:18 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[twitpic]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">http://shkspr.mobi/blog/?p=2073</guid>

					<description><![CDATA[Twitpic has implemented an OAuth API. No more having to hand out passwords to all and sundy.  Only I&#039;m too much of a dunderhead to get it working.  Perhaps it&#039;s a combination of heatstroke or this rotten head-cold, but I just can&#039;t see what I&#039;m doing wrong.  Any help much appreciated.  The easy bit.  It&#039;s easy to post the data to Twitpic  $media_data = array(     &#039;media&#039; =&#62;…]]></description>
										<content:encoded><![CDATA[<p>Twitpic has implemented an <a href="https://web.archive.org/web/20100522065016/http://dev.twitpic.com/docs/2/upload/">OAuth API</a>. No more having to hand out passwords to all and sundy.  Only I'm too much of a dunderhead to get it working.  Perhaps it's a combination of heatstroke or this rotten head-cold, but I just can't see what I'm doing wrong.  Any help much appreciated.</p>

<h2 id="the-easy-bit"><a href="https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/#the-easy-bit">The easy bit.</a></h2>

<p>It's easy to post the data to Twitpic</p>

<pre><code class="language-php">$media_data = array(
    'media' =&gt; '@'.$_FILES['media']['tmp_name'],
    'message' =&gt; html_entity_decode($_POST['message']),
    'key'=&gt;'123465789132465'
);
curl_setopt($ch,CURLOPT_POSTFIELDS,$media_data);
</code></pre>

<h2 id="oauth-credentials"><a href="https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/#oauth-credentials">OAuth Credentials</a></h2>

<p>Using <a href="http://twitter.com/abraham">Abrahams</a> <a href="http://github.com/abraham/twitteroauth">OAuth library for PHP</a>, it's easy to get the required OAuth data.</p>

<pre><code class="language-php">require_once('OAuth.php');
// instantiating OAuth customer
$consumer = new OAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET);
// instantiating signer
$sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
// user's token
list($oauth_token, $oauth_token_secret) = explode('|', $GLOBALS['user']['password']);
$token = new OAuthConsumer($oauth_token, $oauth_token_secret);

// signing URL
$fakeurl = 'https://twitter.com/account/verify_credentials.xml';
$request = OAuthRequest::from_consumer_and_token($consumer, $token, 'GET', $fakeurl, array());
$request-&gt;sign_request($sha1_method, $consumer, $token);
$OAuthurl = $request-&gt;to_url();
</code></pre>

<h2 id="the-tricky-bit"><a href="https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/#the-tricky-bit">The Tricky Bit</a></h2>

<p>I'm following the header example in the <a href="https://web.archive.org/web/20100522065016/http://dev.twitpic.com/docs/2/upload/">API documentation</a>. Passing these variable to Twitpic is where I seem to go wrong.</p>

<pre><code class="language-php">$header = array(
      'X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json',
      'X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/"'
   );
</code></pre>

<p>I then modify the second header so it reads</p>

<pre><code class="language-php">"X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/",
oauth_consumer_key="aaaaaaa",
oauth_nonce="bbbbbbbbbbb",
oauth_signature="ccccccccccccc%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="123456798",
oauth_token="15948715-dddddddddd",
oauth_version="1.0""
</code></pre>

<h2 id="the-error"><a href="https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/#the-error">The Error</a></h2>

<p>401 "Could not authenticate you (header rejected by twitter)."</p>

<p>GAH!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=2073&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2010/05/twitpic-oauth-im-stuck/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
	</channel>
</rss>
