RESTler: stateful REST API fuzzing from an OpenAPI definition
RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.
At a glance
- What is it?
- RESTler is Microsoft Research's stateful REST API fuzzer. It compiles an OpenAPI definition into a grammar, then executes request sequences to find 500s and checker-triggered logic bugs. This review covers the four modes, the Docker and local builds, and where the tool stops being the right choice.
- Who is it for?
- Adopt RESTler if you own a service with a reasonably complete OpenAPI definition and can run it against a disposable or well-isolated environment, starting with compile, then test, then fuzz-lean before fuzz. Do not adopt it if you have no specification to compile, if the service cannot tolerate aggressive request sequences, or if you need a scanner that works from outside with no knowledge of request dependencies.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 112 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem RESTler solves: request sequences, not single endpoints
Most API scanners send one request at a time and check the response. RESTler starts from the opposite assumption: many of the interesting bugs live behind a specific sequence of calls, and the service has to be in a particular state before the bug is reachable. Given an OpenAPI definition, the README states that RESTler analyzes the entire specification and then generates and executes tests that exercise the service through its REST API. It infers producer-consumer dependencies among request types from that definition, which is what lets it chain a create call into a read call into a delete call without a human writing the scenario. The audience is service owners who already have an OpenAPI (formerly Swagger) specification and want automated security and reliability testing against their own cloud service, either locally or inside their CI/CD pipeline. It is not aimed at people who only have a running endpoint and no specification. The dependency inference is the whole product: without it you have a request generator, and request generators are not scarce.
How the compile, test, fuzz-lean and fuzz modes fit together
RESTler runs in four main modes, and the README presents them in order. Compile takes an OpenAPI JSON or YAML definition, optionally with examples, and produces a RESTler grammar. Test executes every endpoint and method in that grammar quickly, for debugging the test setup and computing what parts of the OpenAPI definition are covered; the README also calls this mode a smoketest. Fuzz-lean executes every endpoint and method once with a default set of checkers to see whether bugs can be found quickly. Fuzz explores the grammar in smart breadth-first-search mode for deeper state exploration. The README recommends running test before any fuzzing, specifically to discover and fix setup issues such as adding required pre-requisite parameter values to the dictionary before fuzzing starts. That ordering is a design statement: the tool expects you to spend time on configuration before it does anything interesting. During testing it checks for specific classes of bugs and dynamically learns how the service behaves from prior service responses, which is what allows it to reach states that only appear after particular request sequences. Bugs land in two categories. Any response with status code 500 is reported as a bug. Checkers go further: each one tries to trigger specific bugs by executing targeted additional requests or sequences of requests at certain points during fuzzing, determined by context, and some target logic bugs such as resource leaks or hierarchy violations. When a bug is found, RESTler reports bugs triaged in bug buckets and provides a replay log for reproducing it.
Building RESTler with Docker or a local Python 3.12.8 and .NET 8.0 setup
RESTler was designed for 64-bit Windows or Linux, with experimental macOS support. The Docker path is the shortest. From the root of the repository, the README gives this command:
docker build -t restler .The resulting container has RESTler in /RESTler/restler with main binary Restler. The Dockerfile confirms the layout: a builder stage installs python3 and py3-pip on mcr.microsoft.com/dotnet/sdk:8.0-alpine, runs build-restler.py with --dest_dir /build, and the target stage copies that build into /RESTler. The README notes you can use this image as a basis to add the application under test and fuzz inside isolated containers, which is the safer pattern given what fuzz mode does.
For a local build, the prerequisites are Python 3.12.8 and .NET 8.0. Create a destination directory, then run the build script from the repository root:
mkdir restler_bin
python ./build-restler.py --dest_dir <full path to restler_bin above>The README warns about one concrete failure: if you hit nuget error NU1403 during the build, a workaround is to clear the cache.
dotnet nuget locals all --clearAfter the build, the first real use is not fuzzing. It is compile, then test. The README points to the Quick Start document for trying RESTler on your own API and to the TutorialDemoServer document for a worked example, and the repository ships a demo_server directory and a restler-quick-start.py script at the top level. The README does not reproduce the full compile and test command lines in the main file, so check the Quick Start document for the exact invocation rather than guessing at flags.
Fuzz mode can take down the service under test
The README carries an explicit warning on fuzz mode: this type of fuzzing is more aggressive and may create outages in the service under test if the service is poorly implemented, with fuzzing potentially creating resource leaks, performance degradation, or backend corruptions. That is not a caveat buried in a footnote. It is the single most important operational fact about the tool. Any team planning to point RESTler at production has misread the project. The second limitation is input quality. The compile step needs an OpenAPI definition, and the dependency inference runs on that definition. A thin or inaccurate specification produces a thin grammar, and the README's own advice to add required pre-requisite parameter values to the dictionary before fuzzing tells you the tool will not fill every gap itself. Third, the bug model is narrow by design: a 500 is a bug, and checkers look for specific classes such as resource leaks and hierarchy violations. A service that returns 200 with wrong data in the body is not what this tool is built to catch. Finally, RESTler is a stateful fuzzer, so its results depend on service state; a finding that reproduces in a clean environment may not reproduce in a dirty one, which is exactly why the replay log matters.
RESTler against a stateless OpenAPI fuzzer such as CATS
The natural alternative is a stateless OpenAPI fuzzer, and CATS is the one that appears alongside RESTler in search results. The difference is the unit of testing. A stateless fuzzer takes each operation in the specification, generates malformed or boundary inputs for its parameters, and checks the response in isolation. That is cheap to set up, needs no dependency graph, and cannot corrupt state through a long request chain, because it never builds one. RESTler instead infers producer-consumer dependencies and executes sequences, so it can reach states that a per-endpoint fuzzer never sees. The cost is everything described above: a compile step, dictionary configuration, a test pass before fuzzing, and a real risk of service disruption in fuzz mode. The honest split is that a stateless fuzzer answers whether each endpoint validates its inputs, while RESTler answers whether the service holds together across a sequence of calls. If your API is a set of independent lookups with no shared state, the stateful machinery buys you little and you pay for it in setup time. If your API is a resource lifecycle, the stateless tool will miss the bugs that matter.
Maintenance, licence and what upgrades cost
RESTler is MIT licensed, which permits commercial and internal use with the usual attribution and warranty-disclaimer terms; this is a description of the licence identifier, not legal advice, and you should read the LICENSE file in the repository for the operative text. On maintenance, the repository is not archived and the last push was on 2026-06-10, which is roughly three and a half months before the date of this article. The README states that RESTler was created at Microsoft Research and is still under active development. There are no releases in the release data retrieved for this article, so treat main as the distribution channel and expect to build from source rather than install a tagged artifact. That has a direct upgrade cost: every update means re-running build-restler.py against the new source, and the Docker path means rebuilding the image. The build pins are specific, Python 3.12.8 and .NET 8.0, so a toolchain change on your side can break the build independently of anything RESTler does. The repository also ships a global.json and ci_build_pipelines directory, which suggests the project tracks its own SDK version expectations. If you deploy RESTler in a pipeline, pin the commit you build from and rebuild deliberately rather than tracking main.
Editorial conclusion
Adopt RESTler if you own a service with a reasonably complete OpenAPI definition and can run it against a disposable or well-isolated environment, starting with compile, then test, then fuzz-lean before fuzz. Do not adopt it if you have no specification to compile, if the service cannot tolerate aggressive request sequences, or if you need a scanner that works from outside with no knowledge of request dependencies. Before committing, verify that your OpenAPI definition includes the producer-consumer relationships RESTler needs, that you can supply required pre-requisite parameter values through the dictionary, and that the replay log reproduces a reported bug in your environment.
Frequently asked questions
What is RESTler used for?
RESTler automatically tests a cloud service through its REST API to find security and reliability bugs. Given an OpenAPI definition, it compiles a grammar and executes generated tests, reporting 500 responses and checker-triggered logic bugs.
How do I install RESTler?
Build the Docker image with docker build -t restler . in the repository root, or install Python 3.12.8 and .NET 8.0 and run python ./build-restler.py --dest_dir with a destination directory. The Docker image places the main binary at /RESTler/restler.
What is the difference between RESTler's test mode and fuzz mode?
Test mode executes every endpoint and method quickly to debug the test setup and measure OpenAPI coverage, and is also called a smoketest. Fuzz mode explores the grammar in a deeper breadth-first search and is more aggressive, with the README warning it may create outages in a poorly implemented service.
Does RESTler need an OpenAPI specification?
Yes. The compile mode takes an OpenAPI JSON or YAML definition, optionally with examples, and produces the RESTler grammar that the other modes consume. RESTler infers producer-consumer dependencies among request types from that definition.
What counts as a bug in RESTler?
Any response with status code 500 is reported as a bug. Checkers additionally try to trigger specific bugs by executing targeted requests at certain points during fuzzing, including logic bugs such as resource leaks or hierarchy violations.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/microsoft-restler-fuzzer)