Many classic Windows APIs accept a pointer to a byte buffer and a pointer to an integer indicating the size of the buffer. If the buffer is large enough to hold the data returned from the API, the buffer is filled and the API returns S_OK. If the buffer supplied is not large enough to hold all of the data, the API instead returns ERROR_INSUFFICIENT_BUFFER, updating the supplied integer with the length of the buffer required. The client is expected to reallocate a new buffer of the specified size and call the API again with the new buffer and length.

For example, the InternetGetCookieEx function, used to query the WinINET networking stack for cookies for a given URL, is one such API. The GetExtendedTcpTable function, used to map sockets to processes, is another.

The advantage of APIs with this form is that you can call the API with a reasonably-sized stack buffer and avoid the cost of a heap allocation unless the stack buffer happens to be too small.

In the case of Internet Explorer and Edge, the document.cookie DOM API getter’s implementation first calls the InternetGetCookieEx API with a 1024 WCHAR buffer. If the buffer is big enough, the cookie string is then immediately returned to the page.

However, if ERROR_INSUFFICIENT_BUFFER is returned instead (and if the size needed is 10240 characters (MAX_COOKIE_LEN) or fewer), the API will allocate a new buffer on the heap and call the API again. If the API succeeds, the cookie string is returned to the page, otherwise if any error is returned, an empty string is returned to the page.

Wait. Do you see the problem here?

It’s tempting to conclude that the document.cookie API doesn’t need to be thread-safe–JavaScript that touches the DOM runs in one thread, the UI thread. But cookies are a form of data storage that is available across multiple threads and processes. For instance, subdownload network requests for the page’s resources can be manipulating the cookie store in parallel, and if I happen to have multiple tabs or windows open to the same site, they’ll be interacting with the same cookie jar.

So, consider following scenario: The document.cookie implementation calls InternetGetCookieEx but gets back ERROR_INSUFFICIENT_BUFFER with a required size of 1200 bytes. The implementation dutifully allocates a 1200 byte buffer, but before it gets the chance to call InternetGetCookieEx again, an image on the page sets a new 4 byte cookie which WinINET puts in the cookie jar. Now, when InternetGetCookieEx is called again, it again returns ERROR_INSUFFICIENT_BUFFER because the required buffer is now 1204 characters. Because document.cookie isn’t using any sort of loop-until-success, it returns an empty cookie string.

Now, this is all fast native code (C/C++), so surely this sort of thing is just theoretical… it can’t really happen on a fast computer, right?

Around ten years ago, I showed how you can use Meddler to easily generate a lot of web traffic for testing browsers. Meddler is a simple web server that has a simple GUI code editor slapped on the front (most developers would use node.js or Go for such tasks). I quickly threw together a tiny little MeddlerScript which exercises cookies by loading cookie-setting images in a loop and monitoring the document.cookie API to see if it ever returns an empty string.

Boy, does it ever. On my i7 machines, it usually only takes a few seconds to run into the buggy case where document.cookie returns an empty string.


I haven’t gone back to check the history, but I suspect this IE/Edge bug is at least fifteen years old.

After confirming this bug, it felt strangely familiar, as if I’d hit this landmine before. Then, as I was writing this post, I realized when… Back in 2011, I shared the C# code Fiddler uses for mapping a socket to a process. That code relies on the GetExtendedTcpTable API, which has the same reallocate-then-reinvoke design. Fortunately, I’d fixed the bug a few weeks later in Fiddler, but it looks like I never updated my blog post (sorry about that).


PS: Unrelated, but one more pitfall to be aware of: InternetGetCookieExW has a truly bizarre shape, in that the lpdwSize argument is a pointer to a count of wide characters, but if ERROR_INSUFFICIENT_BUFFER is returned, the size argument is set to the count of bytes required.

PPS: As of Windows 10 RS3, Edge (and IE) support 180 cookies per domain to match Chrome, but the network stack will skip setting or sending individual cookies with a value over 5120 bytes.

Fiddler has long been the tool of choice for developers and testers who are building and verifying APIs exposed over HTTP(S). In this post, we’ll explore the existing features Fiddler offers for API Testing and announce new capabilities we’ve released in Fiddler 2.6/4.6.

Composing API Calls

The Composer tab enables the authoring of arbitrary HTTP(S) requests using any HTTP method, url, headers, and body, and the many Inspectors permit examination of responses of any type, including XML, JSON, BSON, and myriad other formats. Over the last few years, the power of the Composer has grown, and it now offers many conveniences, including a Request History pane:


… to allow simple reuse of existing requests. The powerful Scratchpad tab allows you to easily display a list of requests and execute those requests as needed—a great feature for live demonstrations of your API for tech talks and the like:


As you can see in the screenshot above, the Scratchpad even supports executing requests expressed curl syntax, so you can easily exercise APIs that are documented in terms of the parameters passed to that popular tool.


Capturing API Calls

Of course, Fiddler is best known as a proxy debugger, and its ability to capture traffic from nearly any source means that the fastest way to generate API tests is to simply capture the API traffic from an existing client and modify and augment those tests as desired. You can start with a baseline of the calls your clients presently send, and add new tests to probe for performance, security, error handling, and other problems.

One of the most powerful capabilities Fiddler offers is capture of traffic from almost any device (iOS, Android, Windows, Mac, etc); you can easily exercise your mobile clients’ API endpoints without adding any new software to the device itself!


Resending Requests from the Web Sessions List

After you’ve collected a set of requests in Fiddler, you can easily save them to a Session Archive Zip (.saz) file for convenient reuse at any time. To resend the traffic, just load the SAZ file, select the desired requests, and use the Replay submenu on the Web Sessions list’s context menu to resend the requests. Common choices include:

  • Reissue Requests – Resend the selected requests as quickly as possible
  • Reissue Sequentially – Resend the selected requests, waiting for a response to each before sending the next
  • Reissue and Verify – Resend the selected requests, verifying each response’s status code and body match the original response

Of these options, the last is perhaps the most interesting—you can very easily regression test an API set by simply collecting “good” traffic in a SAZ file and then using that traffic as a baseline against which later verifications will be conducted. The verification performed is rather crude, which is why we’re excited to announce…

Automated API Testing

The new APITest extension to Fiddler greatly enhances its power to validate the behavior of web APIs. Click View > Tabs > APITest to show the APITest tab. The bulk of the tab displays a Test List, a list of API requests and Validators.


Tests can be added to the list by simply dragging and dropping Sessions from Fiddler’s Web Sessions list. You can then use the context menu to specify a Validator and optionally mark it with a Note (comment) and optionally assign it to a group.


Validators offer a lightweight way to judge the success or failure of a test, and support many of the same operators used by Fiddler’s AutoResponder feature. As seen in the screenshot above:

  • EXACT:This is a Test – Ensure the status code matches and response body contains (case-sensitively) the text This is a Test 
  • Updated via API – Ensure the status code matches and response body contains (case-insensitively) the text Updated via API
  • {CODE} – Only ensure the response status code matches the original status, e.g. 201 for the first test
  • {BODY} (Not pictured above) Ensure the response status code matches and the response body is identical 

In addition to the EXACT: operator prefix, the REGEX: and NOT: prefixes are also supported for text searches:


The HEADER: prefix allows you to ensure that the response bears a specified header containing a given value (e.g. HEADER:Content-Encoding=gzip ensures that the response has a Content-Encoding header showing that the response used GZIP compression).

The SCRIPT: prefix allows you to specify a FiddlerScript function in your CustomRules.js file to use to evaluate the response; the named function is passed both the test Session and the baseline (original) Session and can evaluate any criteria you like to return whether or not the test has passed. Beyond examining the headers and body of the response, you could, for instance, evaluate the values in the Session’s Timers object and fail the test if the response took more than 100 milliseconds.

  // This method is called by "SCRIPT:CheckTest" validators; it
  // returns TRUE if the Test passes, and false otherwise.
  static function CheckTest(oRun: Session, oBase: Session): boolean
    // Simplest possible validator
    if (oBase.responseCode != oRun.responseCode)
        oBase["api-lastfailreason"] = "Mismatched status code...";
        return false;

    var timeTotal = 0;
    timeTotal = (oRun.Timers.ServerDoneResponse - oRun.Timers.ClientDoneRequest).TotalMilliseconds;
    if (timeTotal > 100)
        oBase["api-lastfailreason"] = "Performance Too slow...";
        return false;

    return true;   

Script Events

Before your Test List is run, the BeforeTestList method (if present in your FiddlerScript) is run, permitting you to adjust the requests as needed:

  static function BeforeTestList(arrSess: Session[]): boolean
    // In this method, you can do any setup you need for the test,
    // e.g. adding an Authorization: token OAUTH value that you
    // obtained programmatically...
    var sOAUTHToken = obtainToken();
    if (String.IsNullOrEmpty(sOAUTHToken)) return false;

    for (var i: int=0; i<arrSess.Length; i++)
      arrSess[i].oRequest["Authorization"] =  sOAUTHToken;
    MessageBox.Show("Token Set. Running " + arrSess.Length.ToString() +
                    " tests.", "BeforeTestList");

    return true; // Test should proceed; return false to cancel

After all of the individual test cases are executed, the AfterTestList method allows you to validate any post-conditions, log the results of the Test list, or perform other operations. The method is passed a TestListResults object which contains an enumerable list of TestResult objects. Each result contains the baseline (original) Session, the test Session, and an IsPassing boolean indicating whether the test passed. The WriteFailuresToSAZ convenience method will write all failing TestResults to a SAZ file for later analysis.

  static function AfterTestList(listResults: TestListResults)
    for (var oResult in listResults)



Working with Test Lists

A Test List is simply a set of Sessions each of which contains several custom Session Flags (api-testitem, api-Validator, api-LastResult, and api-LastFailReason). As a consequence, these lists can be saved and loaded as regular SAZ files; their “Test List” functionality only lights up when loaded into the APITest tab using its context menu. The menu commands are largely self-explanatory:


  • Run Selected Tests runs only those tests that are currently selected in the UI
  • Rerun Failed Tests runs all tests that are marked as failing
  • Set Comment… sets the Notes column for the selected tests
  • Set Validator… assigns the validation criteria for the selected tests
  • Set Group… assigns the tests to a UI group, useful for organizing your test list
  • Inspect baseline… opens the original Session in Inspectors for viewing or editing
  • Promote moves the selected test earlier in the run order
  • Demote moves the selected test later in the run order
  • Clone creates a copy of the current test, useful when you need to use multiple validators
  • Save Test List saves the test list to a SAZ file
  • Load Test List adds the tests from a SAZ file to the current test list

You can temporarily disable one or more tests from running by pressing the spacebar with the desired tests selected.


While the new APITest extension is offers powerful functionality, many larger enterprises instead choose to use the FiddlerCore .NET Class Library to build their API Testing infrastructure. FiddlerCore allows you to fully customize the behavior of your testing logic, driving the test using the .NET Language of your choice (typically C#). Because FiddlerCore does not utilize any of Fiddler’s UI, it can easily be integrated into existing test automation suites and can be used in console and service applications.

Load Testing APIs

The Fiddler-native Session Archive Zip file format is supported by Telerik Test Studio’s Load Testing product, allowing you to simply import a SAZ file that exercises your API set, configure the number of virtual users and run time, and generate load instantly or on the schedule you set. If you’d like to apply validation logic while your server is under load, run the Load Test in Test Studio and in parallel execute your Test List in Fiddler.


We hope you find Fiddler’s API Testing support useful, and we look forward to your feedback as we continue to enhance the tool.


Eric Lawrence