Runscope was founded in January of 2013 by John Sheehan and Frank Stratton. Since then, the company has raised $7.1 million dollars in financing. The mission of the company is to build tools to support application development lifecycle. One goal of Runscope is to make building with web-based APIs as easy as building with your favorite framework.

At the time of this writing, Runscope offers three tools – Traffic Inspector, Radar, and Passageway. Radar is a continuous integration and functional testing service for APIs. Passageway is a proxy hosted by Runscope that makes it possible to share a development web server running local, accessible to people that are not on the local network.

In this article, we will take a look at Runscope’s Traffic Inspector. Traffic Inspector is a proxy hosted by Runscope that records the lifecycle of requests. The service allows for a convenient way to inspect the headers and body of a request and a response. In order to proxy a request through the Traffic Inspector, Runscope provides a deterministic URL based on the API URL of your choice.


In this case, we are using the Orchestrate API as the endpoint, but we will make requests directly to the Runscope URL. The first request we will inspect is a simple GET requests via a cURL-like tool called HTTPie. Through HTTPie we can see that the exact same response, but with a few extra headers. Namely, the CORs headers and the Runscope-Message-Id header.


All requests are “bucketed” in Runscope, which is a logical partitioning of requests by project, company, bug, etc – ultimately whatever you decide. Buckets can be further partitioned into Collections, which enable developers to logically group requests however they see fit. There are two other main views – the Summary view and the Dashboard Stream view. The Dashboard Stream view shows all requests, while the Summary view groups requests by the method and URI and provides request counts.


Additionally, at the top level view of a bucket, you also have the URL Helper (shown earlier) which helps construct the Runscope proxy URL, the Bucket settings which have administrative and team sharing functions, and finally the Request Editor which is shown below.


In a given request, we now have the ability to “View Request” and “View Response.” Runscope also gives us the ability to notate the request as we debug and inspect. Furthermore, for a given recorded request, the Traffic Inspector tools provides a URL which replays the exact response from the upstream server.


One of the features of the Runscope Traffic Inspector that I found particularly interesting, was the ability to compare requests. To illustrate this feature in Runscope, I will use the Conditional PUT) feature in Orchestrate.

In the case of Orchestrate, a Conditional PUT helps if two actors read an object from Orchestrate and mutate the data object in different ways. When these two actors attempt to write the object back, one of the write requests will fail, ensuring you don’t lose data. For example, imagine two users editing a wiki page at the exact same time. You do not want the first write to be overwritten by the second write.

The example below illustrates two concurrent requests that happen in parallel. To do that, we will use, the concurrent.futures module from the python standard lib ~>3.2. Additionally the below code requires the requests module. The first request we want to succeed, but the second we want to fail. To do that, an HTTP Conditional PUT will be used, with the If-Match header, set to the value of the Orchestrate object reference.

The Orchestrate object reference is a content hash of the object that represents the canonical location of the object. The If-Match header tells Orchestrate “If the content I’m about to overwrite matches this content hash (aka “the ref”), then proceed, otherwise please fail with an error.” The error we are want is an HTTP 412 PRECONDITION FAILED.

import concurrent.futures
import uuid
import json
import requests
API = 'e227c2ba-009a-4336-b0b6-8ed705cb2c8b'          # Orchestrate API Key
URL = ''  # Runscope Bucket URL
KEY = 'runscope'

def write():
    uri = 'https://%s/v0/%s/%s' % (URL, COLLECTION, KEY)
    payload = {"uuid":uuid.uuid4().hex}
    res = requests.get(uri, auth=(API,''))
    ref = res.headers.get('content-location').split('/')[-1]  # Get the Etag value
    return requests.put(uri, data=json.dumps(payload),
                            auth=(API, ''),
                            headers={'if-match': '"%s"' % ref,

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    future_to_data = {executor.submit(write): i for i in [0,1]}
    for future in concurrent.futures.as_completed(future_to_data):
        i = future_to_data[future]
            data = future.result()
        except Exception as exc:
            print('Request %r generated an exception: %s' % (i, exc))
            print('Request %r returned status code: %s' % (i, data.status_code))
            if data.status_code != 201:
                print('\tError: %s' % data.json()['message'])

After running the example a few times in the shell, you will notice a random return of results and a random order of failures.


And now the result in Runscope of comparing the requests, gives us a nice Github-esk diff style, first the requests:


…and then the responses:


In summary, the Runscope Traffic Inspector tool is deceptively simple, but a powerful debugging tool for HTTP APIs. The layout is clean and minimal which makes it a pleasure to look at and use; however, the tools like the Response Playback, Comparison, and Search make it far superior to any locally running proxy you may use for testing. It’s worth noting that in order to proxy requests via the Traffic Inspector, you do have to provide your security credentials. With Orchestrate, I have created a temporary API key, which I have since revoked. In the end, if you’re willing to make the security tradeoff, you get a powerful tool with a great user interface and experience.

UPDATE: John Sheehan, CEO of Runscope, has graciously offered our readers access to a Runscope Standard Account for free, just follow Thanks John!