spindas: (raccoon)
[personal profile] spindas
Firewatch is a story-centric game by Campo Santo and Panic. I played it all the way through this weekend and had a really great time with it. Besides the top-notch voice acting, gorgeous visuals, and mystery-filled plot, one feature that’s been getting a lot of attention is the disposable camera the player carries through most of the game. Starting with 18 unused shots on the roll, you can fill it up with snaps of trees and trails and plenty of sunsets peaking over the hills. At the end they’re all uploaded to a personal page on Firewatch.camera, where you can share them or order prints from the "Fotodome".

Firewatch photo upload screen

At the end of my own playthrough, I uploaded my shots and logged onto the site to see them.

My camera roll

But one of them came out… weird.

Huh, that's weird

Strange distortion! And are those bits of QR codes in the corners? Could this be the beginnings of an ARG?!

I posted the Firewatch.camera link to r/Firewatch, a discussion board for the game on Reddit, to see what the resident internet detectives could make of it.

Reddit submission

Reddit discussion

Redditors sprang into action, loading the weird pic into Photoshop, filtering and cutting and turning it about in hopes of shaking out a secret.

Found a QR code!

My hunch was right—that was a QR code! Cleaned up and put back together, they found it led to…

The big secret

Reddit reacts (1)
Reddit reacts (2)
Reddit reacts (6)

Okay, maybe that's not exactly how it all happened.

Truth is, as I stared at the photo upload screen in a post-game slump, I got to wondering whether I could send in any old photo from my PC and have Panic print it off with the rest of the batch. I figured the game program probably sent the files to a hidden HTTP endpoint on firewatch.camera, so I broke out Charles Proxy, my tool of choice for HTTP interception. I like it because it’s easy to set up and supports SSL decryption, but other tools like mitmproxy could probably do the job as well. Looping back through the ending sequence again, I watched as my photos were retransmitted to The Cloud—this time with Charles listening in.

Charles picked up several requests to endpoints on https://www.firewatch.camera/api/v1/roll/. I reconstructed the first, to roll/create/form, with cURL on the command line:

curl -H "User-Agent: UnityPlayer/5.2.4f1 (http://unity3d.com)" \
     -H "X-Unity-Version: 5.2.4f1" \
     -X POST --data "email=bob@example.com" \

The -H flags let us set custom headers so our request looks like it’s coming from Unity, the engine the game was built in. The next line sends along an email address (to which Firewatch Camera will send our photos page) with the HTTP POST request. Further experimentation revealed that this field can be left blank.

As luck would have it, the server was happy to handle my request, responding back:


My original Firewatch.camera page appeared at https://firewatch.camera/SoftAcadiaCamp/, so I inferred that create gives back a unique key for the new set of photos.

Mimicking the flow that Charles mapped out, the next step was to send in a JPEG image to roll/EvergreenBasinDrive/upload_photo:

curl -H "User-Agent: UnityPlayer/5.2.4f1 (http://unity3d.com)" \
     -H "X-Unity-Version: 5.2.4f1" \
     -X POST -F index=17 -F photo=@firewatch.jpg \

The game submits photos in reverse order, with an index parameter starting at 17 and counting down to 0 for a full batch. (It won’t take more than 18 photos total—I’ve tried.) The -F photo=@firewatch.jpg tells cURL to attach the contents of firewatch.jpg on my system as a file upload called "photo".

In short order I heard back from the server again:


"status": "OK"

Alright! One photo submitted. A couple more and it was time to try out the last endpoint on the list, roll/EvergreenBasinDrive/complete. Again matching the Charles log:

curl -H "User-Agent: UnityPlayer/5.2.4f1 (http://unity3d.com)" \
     -H "X-Unity-Version: 5.2.4f1" \
     -X POST --data="success=1" \


    "status": "OK"


Presto! My custom photoset was finalized and visible at https://www.firewatch.camera/EvergreenBasinDrive/.

Custom camera roll

Some more playing around along these lines let me suss out the remaining requirements and error cases in the API. I bundled this knowledge into a plug-and-play Node.js library and command line tool as a little demo.

node-firewatch.camera on GitHub

With that all done, we can get back to the original joke! Inspired by the internal name roll (short for "camera roll") used in the API, I:

  • grabbed my real Firewatch pics from their Firewatch.camera page,
  • made a Rick Roll QR code,
  • whipped up the fake, distorted shot in GIMP, splitting up the QR code and hiding it inside, and
  • used my new tool to upload it to a new Firewatch.camera page, alongside some of those photos I actually took in game.

All that remained was to stick the link on Reddit and let the fun unfold. 😉

January 2017

29 3031    

Most Popular Tags

Page generated Apr. 26th, 2019 01:59 am
Powered by Dreamwidth Studios