Charlie DeTar on Occupy Streams Map

Video source

One interesting aspect of the Occupy movement has been the widespread use of live streaming to document the camps, actions, and mobilizations in real time using computers, webcams, and cameraphones. On October 24th, I ran across the Occupy Streams site that provides a list of links to all of the livestreams run by Occupiers. I forwarded a link to the site to the general email list used by researchers at the Center for Civic Media:

>> On 10/24/2011 10:36 PM, Sasha Costanza-Chock wrote:
>> Someone make a map, with thumbnails, already 🙂
>> schock

By the next morning, I found this reply in my inbox:

>> > On Tue, Oct 25, 2011 at 7:25 AM, Charlie DeTar wrote:
> ok.
>> -charllie

Later, Charlie DeTar wrote a blog post describing the map that he created. Today, during the #OccupyData hackathon, CDT gave us a more detailed overview of the process he used to code the map. The video at the beginning of this post is a full recording of that overview, shot by Pablo Rey Mazon. Check it out!

Key Links


Content of

A simple little mapping hack to show occupy live streams.


1. Scraping:

Look for patterns.
Caching http requests during development.

2. Geocoding


result = json.loads(get_cached_page(“” % urllib.quote_plus(locname.encode(‘utf8’))


Don’t be afraid to hard-code results.

if locname.startswith(“Wall Sreet”): # [sic]
locname = “Wall Street, NY”
elif “London” in locname:
locname = “London”
elif “Denver” in locname:
locname = “Denver”


3. Mapping


Removing overlaps


Simplest, dirty hack: just add intentional error.

while (overlaps[[lat, lng].join(” “)]) {
lng += 0.02;

Popup generation — hackish javascript -> html

Mapquest OSM tiles:

Construct icons for each point, with the livestream thumbnail.

I couldn’t find a thumbnail API for ustream. So I just used the ustream icon for those.

Live thumbnail updates for livestream:

4. Geo-Search

Cloudmade API:

Automatically took first result.


no tricky rules about displaying data on google maps from cloudmade.


Some first results aren’t quite what you expect. Search for “Paris”.

To fix this issue, I tried contextualizing the result with the next-largest geographic entity, so when it was wrong, you’d at least know:

var names = [data.features[0]];
if (data.features[0].properties[“is_in:country”]) {
} else if (data.features[0].properties[“is_in:continent”]) {
} else if (data.features[0].properties[“is_in”]) {
if (data.features[0].properties.population) {
names.push(“<br />Population: ” + data.features[0].properties.population);
}$(“.results”, “.search”).html(names.join(“, “));