This is the first of a two-part series on using social media to locate eyewitnesses to important events. In this tutorial, I'll guide you through using the Instagram API to find members that might have been near a 2013 Macklemore video shoot and a Seattle accident scene near where I often work.
In part two, we'll use the Twitter API to find members near another recent event. I'll also address some of the privacy issues related to social media and sharing your geolocation. You can download code for each episode by using the GitHub repository link in the sidebar. You may also be interested in my Tuts+ series, Building With the Twitter API.
I do participate in the discussions. If you have a question or topic suggestion, please post a comment below. You can also reach me on Twitter @reifman or email me directly.
Using Geotagging for Good (and Evil)
The phones we carry in our pockets record our every move, sharing it with cell providers and often third party software companies whose motivations generally focus on profit. But it's not just phones and GPS that expose us—I almost always make purchases with credit cards, exposing pretty much every aspect of my life to credit card providers, hackers, or legal requests.
Wired's Vanish Contest
In Wired's 2009 Vanish contest, I helped lead the capture of journalist Evan Ratliff. After writing about people who fake their deaths, Ratliff tried to disappear for 30 days as part of an experiment. If anyone could find him in person before time expired, they'd receive a $5,000 prize. Using a Facebook application as a honeypot, I was able to lure Ratliff into repeatedly sharing his location via IP address, which I then verified against a Twitter account I'd discovered he was using. With help from other Vanish participants nationwide, we called in help on the ground in New Orleans—which came in the form of a gluten-free pizza shop (Ratliff was known to be celiac) who managed to track him down in town. In that story, geotagging wasn't used to find him but IP address geolocation. You can read Ratliff's story here as well.
But social media applications on our phone frequently make use of geotagging, leaving a trail that users don't always anticipate.
Muckraking With Geotags and Social Media
Many people don't realize that they've left geotagging on their social media apps, fully publicizing their location with every social media post. This included GOP Congressman Aaron Schock. The AP used his Instagram account's geotags to expose his use of taxpayer funds for extravagant private flights and other luxurious activities. See Instagram account exposes congressman who blew public funds on private flights and concerts.
Here's an Instagram post by Schock from Patagonia—notice the geotag icon beside "Perito Moreno Glacier":
So, investigating geotags can be used for good. In this tutorial, I'm going to explore how journalists or law enforcement might locate potential eyewitnesses to important events such as a crime or accident scene using social media.
However, geotagging can also be used for evil. There are definitely important privacy implications of its integration into our digital lifestyle.
Privacy Implications
Berkeley computer scientists and educators built the Ready or Not? app to showcase how geotagging in Twitter and Instagram record our every move. See also Is Your Twitter Account Saying Too Much?
Here's Congresmmen Schock's Instagram account in the Ready or Not? app:
Here's Apple co-founder Steve Wozniak's Twitter account in the app. Interesting that the congressman's travel is even more widespread than this tech tycoon.
The geotagging on Instagram and Twitter is accurate enough to allow someone to easily determine your residence, place of work and travel routine.
Turning Off Geotagging
If you don't wish to share your location for the public to see, or to leave a historical trail of your travels, the Ready or Not? app offers links and guides to turning these features off (look for the link on its home page). Frankly, I've turned mine off and I encourage you to do so too.
For those that don't—and many won't—their social media posts may be useful to law enforcement looking for witnesses to a crime scene or journalists wishing to dig deeper into a story. I'm going to guide you through how to do that.
In this episode, I'll guide you through using the Instagram API. I've provided a GitHub repository (the link is in the sidebar) for you to download to try out the code. My "Eyewitness app" is written in the Yii Framework for PHP, which you can learn more about in my Programming With Yii2 series for Tuts+.
The configuration process requires that you register a developer account and application with Instagram (and/or Twitter).
If you're a law enforcement agency or media entity that would like more information, please feel free to contact me directly. I would also be interested in any successful uses of this code (for good)—they'd make an interesting follow-up story.
Using the Instagram API
Let's begin with Instagram. If you don't yet have an Instagram account, download the application on your phone and sign up.
Instagram Media Search
The geolocation search on Instagram is quite sophisticated and offers a very straightforward interface for our purposes. As you can see below, we need to provide a location's latitude and longitude, a geographic radius (distance) and a time range (min_timestamp and max_timestamp):
Getting Started
Visit the Instagram API page for developers and click Register Your Application:
You'll need to sign up for a developer account:
Then you can register a new application to receive your Client ID:
On the Manage Clients dashboard, you'll see your Client ID and Client Secret, so make note of these:
Installing the Eyewitness Codebase
You can clone the GitHub repository located in the sidebar to run our sample code.
cd ~/Sites/eyew https://github.com/link-in-sidebar/eyew.git
You'll need to configure your local Apache configuration. I use MAMP, so it looks something like this:
cd /Applications/MAMP/htdocs ln -s ~/Sites/eyew/web /Applications/MAMP/htdocs/eyew
You need to create a database locally. I use PHPMyAdmin to create one graphically:
Then I create an initialization file in /var/secure/eyew.ini with my database credentials and Instagram IDs and keys. I described this process recently in another Tuts+ tutorial: Protecting Your Keys From GitHub. Humorously, I accidentally checked in my Instagram key during testing (sigh) and had to reset my keys afterwards.
My ini file looks like this:
mysql_host="localhost" mysql_db="eyew" mysql_un="xxxxxxxxx" mysql_pwd="xxxxxxxxxxxx" instagram_client_id = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7" instagram_client_secret = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4"
Update your Composer and its vendor libraries:
sudo composer self-update sudo composer update
Then initialize our database. The first migration installs user tables for our Yii2-User by developer Dmeroff extension, and the second creates our app-specific tables:
./yii migrate/up --migrationPath=@vendor/dektrium/yii2-user/migrations ./yii migrate/up
Again, you can learn more about setting up a Yii Framework application in my Programming With Yii2 series for Tuts+.
The Eyewitness Home Page
Here's a look at what you should see when you visit the site in your browser:
Define a Moment
A Moment is a place and time for which we're looking for social media posters who were present. It consists of a friendly descriptor, a location (latitude and longitude), a start time and a duration (in minutes). For my first example, I'm looking for Instagram users who were present at Macklemore's video shooting on the evening of Wednesday, July 24, 2013 at Seattle's landmark Dick's Drive In. The video production and ensuing crowds shut down the area for hours.
Using Google Maps, I can get the GPS latitude and longitude for Dick's. It's 47.6195 -122.321.
From the article, I learned that the production shut down at 1 am. I'm going to choose a start time of 10 pm and a duration of 3 hours.
Instagram accepts start times in GMT so I've hardcoded an eight hour time change adjustment from my timezone (PST). You may need to change this in the code.
public function actionCreate() { $model = new Moment(); if ($model->load(Yii::$app->request->post())) { // convert date time to timestamp $model->start_at = strtotime($model->start_at); // adjust for GMT $model->start_at+=(3600*8); // validate the form against model rules if ($model->validate()) { // all inputs are valid $model->save(); return $this->redirect(['view', 'id' => $model->id]); } else { return $this->render('create', [ 'model' => $model, ]); } } else { return $this->render('create', [ 'model' => $model, ]); } }
Moment Search on Instagram
To search Instagram, we click the camera icon below:
To implement my media search on Instagram, I'm using Galen Grover's Instagram PHP package. The actual search is fairly straightforward: $instagram->searchMedia( $this->latitude, $this->longitude,$params );
<?php namespace app\models; use Yii; use yii\db\ActiveRecord; use app\models\Gram; use Instagram; ... public function searchInstagram() { $instagram = new Instagram\Instagram; $instagram->setClientID( \Yii::$app->params['instagram']['client_id'] ); $end_at = $this->start_at + ($this->duration*60); $params = array('min_timestamp'=>$this->start_at,'max_timestamp'=>$end_at,'distance'=>$this->distance,'count'=>50); $media = $instagram->searchMedia( $this->latitude, $this->longitude,$params ); foreach ($media as $m) { if (isset($m->caption->text)) { $caption = $m->caption->text; } else { $caption =''; } $i = new Gram(); $i->add($this->id,$m->user->username,$m->link,$m->created_time,$m->images->thumbnail->url,$caption); } }
The results are stored in my Gram table, which we can then browse:
public function add($moment_id,$username,$link,$created_time,$image_url,$text) { if (!Gram::find()->where(['moment_id' => $moment_id])->andWhere(['link'=>$link])->andWhere(['created_time'=>$created_time])->exists()) { $i = new Gram(); $i->moment_id = $moment_id; $i->username = $username; $i->link = $link; $i->created_time = $created_time; $i->image_url = $image_url; $i->text = $text; $i->save(); } }
Browse the Results
Here's the first page of results from my search. You can see the crowds and Macklemore's Cadillac limo driving up. Clearly, I hit the jackpot with my search.
Then on page three, an Instagram user named Joshua Lewis has a shot of Macklemore exiting the Cadillac:
Here's Macklemore:
This example clearly shows the power that the Instagram search API provides. In just a few moments, we found a variety of eyewitnesses to an event from the summer of 2013. Amazing.
If you're interested, here's a YouTube video of that Macklemore shoot:
Another Example Moment
For my second example, I'm going to search for Instagram users who were in the area around the time of a tragic accident near where I was co-working a few weeks ago. A woman's motorized scooter may have malfunctioned and she lost control, crashing into the tail end of a passing car (thankfully, she survived). It happened in front of the Starbuck's "Roastery", an unfortunate new tourist trap here in Seattle (I'm not a fan).
Using Google Maps, we can see the GPS coordinates of the roastery to be 47.614264, -122.328008:
The article tells us that the accident happened around 5 pm. So we'll use this information to create our Moment:
Here you can see both moments we've added:
In case you were wondering, the eraser icon purges past results for that moment search.
Here's the results for our Starbucks Roastery accident search. No one posted photos of the accident scene—common courtesy prevailed. However, all of these Instagram users were in the area at the time and might be worth contacting as witnesses.
Some were tourists like this Russian woman—I've posted the Google translation of her Instagram post below:
Others visited the Starbucks roastery tasting room or a nearby bar and oyster restaurant.
I hope that you can see both the dark and the light of geotagging technology. There are obvious legitimate uses that these technologies can provide for good, and they can obviously be abused.
What's Next?
In the next episode, we're going to implement searching moments using the Twitter API.
In the meantime, please feel free to post your questions and comments below. You can also reach me on Twitter @reifman or email me directly. I'd especially appreciate hearing from journalists and law enforcement that make use of these examples.
You can also browse my Tuts+ instructor page to see other tutorials I've written.
Comments