Getting Flickr::API to work on Ubuntu Linux SOLVED

In order to use the Flickr::API example by Gabor Szabo, I needed to create a LWP object specifying the path to the system certificates when creating the Flickr::API object.


my $flickr_api = Flickr::API->new( {
    key       => $key,
    # secret  => $secret,
    unicode   => 1,
    lwpobj    => LWP::UserAgent->new(
        ssl_opts => { 
            SSL_ca_path => '/etc/ssl/certs',

Doesn’t work Perl(reports a 500 error with “Can’t connect to (certificate verify failed)” ) :

my $flickr_api = Flickr::API->new( {
    key       => $key,
    # secret  => $secret,
    unicode   => 1,
    ssl_opts  => { 
        SSL_ca_path       => '/etc/ssl/certs',

You could use Mozilla::CA as brian d foy suggests but the bundled file is from 2014. Personally, I’ll use the certificate files from the OpenSSL project. 🙂

Share Button

Perl and Flickr: Flickr::Simple2

I’m in the process of cleaning up Flickr::Simple2 and adding in support for oauth.  There are several Perl modules providing oauth which I will test for ease of use and maintainability.  Just an fyi at this point

Share Button

The GIMP: “A beautiful Russian friend of Mine” by Frank Kovalchek

Original photo by Frank Kovalcheck:

Just a little bit of tweaking in The Gimp

  1. increased the contrast on the model using the curve tool.
  2. Anisotropic smoothing of her body sans eyes with an amplitude of 230 and ansiotropy of 0.5 using GREYC’s Magic Image Converter (G’MIC) plugin
  3. increased the contrast on her eyes
  4. followed by unsharp mask with a radius of 5.0 amount 0.5 and threshold of 0 on her eyes

Share Button

Greater Chicago Jewish Folks Art Festival Flickr Group

If you’ve attended the Greater Chicago Jewish Folks Art Festival and took photos, please share your photos with the rest of the world! It doesn’t matter what year or if they’re fuzzy or overexposed.. we love all the photos 🙂

I just created the Flickr photo group Greater Chicago Jewish Folks Art Festival so everyone can share their photos from the Greater Chicago Jewish Folks Art Festival:
Flickr is almost certainly the best online photo management and sharing application in the world. Show off your favorite photos and videos to the world, securely and privately show content to your friends and family, or blog the photos and videos you take with a cameraphone.

Share Button

Perl module Flickr::Simple2 v0.03 for the Flickr API released!

I just uploaded the Perl module Flickr::Simple2 version 0.03 to CPAN (PAUSE) so it might be a few minutes/hours before it shows up in the CPAN mirrors.

Revision history for Perl extension Flickr::Simple2.

0.03  Wed May 13 11:18:00 2009
– significant changes to the API to make more methods of the Flickr API available.
– using Iterator::Simple so we can retrieve one photo at a time and internalize the handling of Flickr Photo *pages*
0.02  Initial CPAN release
0.01  Thu Feb 12 11:33:35 2009
– original version; created by h2xs 1.23 with options
-XA -n Flickr::Simple2

Share Button

First official release of Flickr::Simple2 to Perl’s CPAN repository :)


Flickr::Simple2 is an XML::Simple based Perl API to communicate with Flickr.  It is in the early phases of development… comments are welcome :)

You will need to supply your own Flickr API key.

I released version 0.02 to Perl’s CPAN repository this morning after several delays related to the birth of my son a week ago.  As always, comments and constructive critism are welcome.

Share Button

Alpha test release of Flickr::Simple2

FlickrFlickr::Simple2 is an XML::Simple based Perl API to communicate with Flickr.  It is in the early phases of development… comments are welcome 🙂

You will need to supply your own Flickr API key.

Share Button

Looking for photos from Sybase TechWave 2008? Check out the Sybase TechWave 2008 Flickr group!

Go to Sybase TechWave 2008 Flickr group

Share Button

FW: Photos from Yet Another Perl Conferences (YAPC)

From Jeremy Fluhmann:

For all of you first time yapc attendees, I thought you might be interested in some of the photos from previous yapcs.  I’m sure there are others, but some of the links from Flickr are:

Chicago in 2006 –
Houston in 2007 –
YAPC::NA in general –
YAPC in general –

And, I’m assuming that this year (as with the previous two years) someone will recommend tagging the 2008 photos with yapcna2008.  I’d recommend also tagging them with yapcna and yapc.


Conferences Chair
The Perl Foundation

Share Button

If you’ve ever tried to back up your Flickr account or download the public Flickr photos of other users, then your options were pretty limited on Linux. After trying and failing to get FlickrDown to work under wine, I decided to write my own… in perl 🙂

The various Flickr API’s on CPAN are incomplete with respect to obtaining the list of public/friends photos. I had to use XML::Parser::Lite::Tree::XPath to extract the photos from each Flickr page.

By default, we obtain the largest photo available (orginal -> large -> medium -> small), populate the EXIF comments field with the Flickr photo title, description and url. We verify the file type with File::MimeInfo::Magic and change/add the file extension as necessary.

During testing I received numerous duplicate files which were mostly resolved by adding a rudimentary duplicate file checker.

It should work on just about any platform that Perl does.



use strict;
use warnings;

use Digest::MD5 qw(md5_hex);
use Config::Simple;
use Image::ExifTool;
use File::MimeInfo::Magic qw(mimetype extensions);
use Flickr::API::Photos;
use Flickr::Person;
use Getopt::Std;
use HTML::Entities ();
use File::MimeInfo::Magic;
use IO::Scalar;
use LWP;
use Tie::File::AsHash;
use XML::Parser::Lite::Tree::XPath;


my $cfg = new Config::Simple('FlickrDownload.ini');

my $user_name;
my $id;
my $email;
my %arg_options;
my $photo_directory;
my $found;

getopts('e:i:u:', \%arg_options);

$user_name = $arg_options{u};
$id = $arg_options{i};
$email = $arg_options{e};

my $flickr_api_key = $cfg->param('Flickr.API_KEY');
my $flickr_secret = $cfg->param('Flickr.API_SHARED_SECRET');
my $flickr_email = $cfg->param('');
my $flickr_password = $cfg->param('Flickr.password');

sub decode_html {
  my $string = shift;

  my $new_string = HTML::Entities::decode($string);

  if ($string ne $new_string) {
    $new_string = decode_html($new_string);

  return $new_string;

my $flickr_person = Flickr::Person->new( {
    api_key    => $flickr_api_key,
    email    => $flickr_email,
    password  => $flickr_password
  } );

if ($user_name) {
  $found = $flickr_person->find( { username => $user_name } );
} elsif ($email) {
  $found = $flickr_person->find( { email => $email } );
  $user_name = $flickr_person->username();
  $found = $flickr_person->find( { username => $user_name } );
} elsif ($id) {
  $found = $flickr_person->id( {id => $id} );
  $user_name = $flickr_person->username();
  $found = $flickr_person->find( { username => $user_name } );

if ( $found ) {
  my $page_num = 1;
  my $more_pages = 1;
  my $api = $flickr_person->{people_api}->{api};

  $photo_directory = $cfg->param('') . "/" . $user_name;
  $api->{api_secret} = $flickr_secret;

  my $flickr_photos = Flickr::API::Photos->new(

  unless (-d $photo_directory) {
    mkdir $photo_directory
      or die ('Unable to create directory "' . $photo_directory . '"' );

  # for determine whether we might be downloading a duplicate, we need a hash with
  #   the MD5 sum & filename.  We tie both hashes to a file in the flickr user's
  #   directory
  tie my %MD5_HASH, 'Tie::File::AsHash', $photo_directory . "/.md5s", split => ':'
    or die "Problem tying %hash: $!\n";

  tie my %FILES_HASH, 'Tie::File::AsHash', $photo_directory . "/.files_md5s", split => ':'
    or die "Problem tying %hash: $!\n";

  while ($more_pages) {
    my $response = $api->execute_method('flickr.people.getPublicPhotos', {
      api_key    => $flickr_api_key,
      user_id    => $flickr_person->id,
      per_page  => 500,
      page    => $page_num
      } );

    my $xpath = new XML::Parser::Lite::Tree::XPath($response->{tree});
    my @nodes = $xpath->select_nodes('/photos/photo');

    if ($#nodes > 0) {
      foreach my $node (@nodes) {
        my $original_photo;
        my $photo_id = $node->{attributes}->{id};
        my $photo_hash = $flickr_photos->getInfo($photo_id);
        my $photo_title =
            ? $photo_hash->{'title'}
            : "";
        my $description =
            ? decode_html( $photo_hash->{'description'} )
            : "";

        my %photo_sizes =
          map { $_->{'label'} => $_ }
            @{ $flickr_photos->getSizes($photo_id)->{sizes} };

        if (exists $photo_sizes{'Original'}) {
          $original_photo = $photo_sizes{'Original'};
        } elsif (exists $photo_sizes{'Large'}) {
          $original_photo = $photo_sizes{'Large'};
        } elsif (exists $photo_sizes{'Medium'}) {
          $original_photo = $photo_sizes{'Medium'};
        } elsif (exists $photo_sizes{'Small'}) {
          $original_photo = $photo_sizes{'Small'};
        } else {
          warn "Unable to find url.  Skipping photo."

        printf "name: %s id: %s description: %s\n",

        my $photo_filename = $photo_directory . '/' . $photo_title;
        $photo_filename =~ s/\.\w+$//;

        # Prepopulating the file extension will allow us to eliminate
        #   the vast majority of duplicate images by not downloading
        #   them in the first place.
        if (exists $photo_hash->{'originalformat'}) {
          my $extension = $photo_hash->{'originalformat'};
          $photo_filename .= "_" . $photo_hash->{'id'} . "." . $extension;
        } else {
          # if we don't know at this point what format the image file is
          #   without downloading the image, we can assume it is a jpg
          #   because the vast majority of the photos are jpg.
          $photo_filename .= "_" . $photo_hash->{'id'} . ".jpeg";

        if (-f $photo_filename && (stat($photo_filename))[7] > 2048) {
          printf "We already have photo %s .. Skipping\n", $photo_title;
        } else {
          my $FH;

          my $request = HTTP::Request->new(GET => $original_photo->{'source'} );
          my $response = $api->request($request);
          my $md5_sum = md5_hex($response->content);

          # since we have downloaded the photo, let's put the proper file
          #   extension on it.
          if (my $file_ext = extensions( mimetype(new IO::Scalar \($response->content) ) ) ) {
            $photo_filename =~ s/\.\w+$//;
            $photo_filename .= "." . $file_ext;

          if (exists $MD5_HASH{$md5_sum}) {
            printf "We already have photo %s .. Skipping\n", $photo_title;
          } else {
            $MD5_HASH{$md5_sum} = $photo_filename;
            $FILES_HASH{$photo_filename} = $md5_sum;

            open($FH, ">", $photo_filename)
              or warn ("Unable to write to $photo_filename.\n" );

            binmode $FH;
            print $FH $response->content;
            close $FH;

            # We're going to use Image::ExifTool instead of the built in
            #  exif extracted information from Flickr::API::Photos because
            #  we want to write to the file.
            my $exifTool = new Image::ExifTool;
            my $info = $exifTool->ImageInfo($photo_filename);

            unless ($info->{'DateTimeOriginal'}) {
              if ($photo_hash->{'dates'}->{'taken'}) {
                my $taken_date = $photo_hash->{'dates'}->{'taken'};
                $taken_date =~ s/\-/\:/g;
                $exifTool->SetNewValue("DateTimeOriginal", $taken_date);

            $exifTool->SetNewValue("Comment", $photo_title . ": " . $description . " " . $original_photo->{'source'});
            my $result = $exifTool->WriteInfo($photo_filename);

    } else {
      $more_pages = undef;

    untie %MD5_HASH;
    untie %FILES_HASH;



#  where you want to put the photos
Share Button