Monkey testing is the practice of throwing unpredictable input at software to see whether it falls over. No test plan, no expected results, no careful setup — just interaction, at volume, in an order nobody designed for.
The name comes from the infinite monkey theorem: a monkey hitting keys at random for long enough will eventually type Hamlet. Point enough random input at an application for long enough and you will eventually find the input that crashes it.
It sounds unserious. It is one of the oldest and most stubbornly useful techniques in QA, and after twenty years as a niche tool it is worth another look — because the thing that always limited it has finally been solved.
Every test you write encodes an assumption about how the software will be used. That is the point of a test, and it is also its blind spot. You test the checkout flow because you know checkout matters. You do not test what happens when someone hits the back button mid-payment, opens a second tab, and submits the form twice — because it never occurred to you, and it never occurred to your test suite either.
Real users do all of this. Not because they are trying to break anything, but because they get interrupted, they misread a label, their connection drops, they tab backwards through a form, they paste 4,000 characters into a field expecting a postcode.
Monkey testing covers the space your imagination did not. It is deliberately unguided so that it explores paths a person designing tests would never write down.
The literature splits monkey testing into three tiers, and the distinction matters a lot in practice because they find completely different classes of bug.
A dumb monkey knows nothing about the application. It taps random coordinates, sends random keystrokes, swipes in random directions. It has no idea what a button is, let alone what your app does.
Android’s built-in adb shell monkey is the canonical example: it fires a stream of pseudo-random UI events at a device and reports when the app crashes.
What dumb monkeys find: hard crashes, unhandled exceptions, memory leaks, race conditions from rapid input, and anything that dies when handed input outside the expected range.
What they miss: everything that requires reaching a meaningful state first. A dumb monkey will essentially never fill in a valid email, a valid password, and click “Sign up” in that order. So it never gets past your login screen, which means it never tests your product.
A smart monkey has some model of the application. It knows where the clickable elements are, it knows which states exist, it may know that certain regions of the app are more valuable to explore than others. It still chooses unpredictably, but from a set of plausible actions rather than arbitrary screen coordinates.
Gremlins.js, which unleashes clicking, scrolling and typing “gremlins” on a web page, sits roughly here: it targets real DOM elements rather than raw pixels.
What smart monkeys find: everything a dumb monkey finds, plus broken navigation, state that gets corrupted by an unusual sequence of legitimate actions, and UI that breaks under rapid interaction.
What they miss: anything requiring semantically valid data. Knowing that a field is a text input does not tell you it wants a UK postcode.
A brilliant monkey understands the domain. It knows this is an e-commerce checkout, so it knows a user would add an item, enter a shipping address, choose a payment method, and expect a confirmation. It behaves like a user with an agenda rather than a user with a twitch.
This tier has been described in testing literature for decades and, until recently, was effectively theoretical. Encoding domain understanding meant a human writing it down — at which point you have not built a monkey, you have written a test suite by hand, and you are back where you started.
Large language models are, among other things, quite good at looking at a rendered page and inferring what it is for.
Show one a page with a product grid, a cart icon and a “Proceed to checkout” button, and it will tell you this is an e-commerce site and that a user would probably add an item to the basket and try to buy it. It will generate a plausible name, a plausible address, a plausible card number format. It knows what “valid input” means for a field labelled “Postcode” because it has read the internet.
That is the missing ingredient the brilliant monkey always needed, and it is available now for fractions of a cent per call.
This is what modern AI monkey testing actually is: the unguided, no-test-plan, explore-what-nobody-thought-of spirit of monkey testing, with a model supplying the domain understanding that used to have to come from a person.
It is also why the technique is worth revisiting if you dismissed it years ago. The objection was always “random clicking never gets anywhere useful”. That objection no longer holds.
Four techniques share DNA with monkey testing and get used interchangeably, usually incorrectly.
Fuzz testing feeds malformed or unexpected data into a program’s inputs — file parsers, network protocols, APIs — looking for crashes and memory-safety failures. Fuzzing operates at the data layer; monkey testing operates at the interaction layer. Tools like AFL++ and libFuzzer are fuzzers, not monkeys. They are excellent at finding buffer overflows and terrible at finding a checkout button that does nothing.
Gorilla testing is the opposite of monkey testing despite the primate branding. Gorilla testing hammers one specific module repeatedly and exhaustively until you are confident it is bulletproof. Monkey testing spreads thin across everything. One goes deep on a known target; the other goes wide on unknown ones.
Chaos engineering — Netflix’s Chaos Monkey and its descendants — kills infrastructure: servers, availability zones, network links. It tests whether your system survives failure. It has nothing to do with UI input, and the shared “monkey” naming has confused a decade of engineers.
Ad hoc and exploratory testing are humans poking at software without a script. Exploratory testing in particular is a skilled discipline, not randomness — a good exploratory tester forms hypotheses and chases them. Monkey testing is what you use to cover ground when you do not have a human’s time to spend.
It is worth being clear about what this technique is and is not good for, because overselling it is how it got a bad reputation in the first place.
It is good for:
It is not a replacement for:
The honest framing is that monkey testing is a complement. It covers the enormous surface area nobody has written a test for yet, which — if you look at where escaped production bugs actually come from — is where most of them live.
Classic monkey testing had three problems that kept it off most teams’ roadmaps:
Each of these has an answer now.
Noise goes away when the monkey is choosing goal-directed actions rather than arbitrary ones — a failure in “add to cart, checkout, pay” is a bug your customers hit today. Reproducibility comes from writing the chosen flows out as a stable, versioned plan you can re-execute exactly. And reachability is exactly what domain understanding buys you: a model that can generate a valid signup gets past the signup.
That is the shape of every serious tool in this space now, including the one we build: explore the site, decide what a real user would try, execute those flows deliberately, and record the plan so tomorrow’s run is comparable to today’s.
If you want to try the technique on a web application, you have three realistic options.
Roll your own with Playwright or Puppeteer — write a script that walks the DOM and clicks things semi-randomly. Cheap to start, and you will spend more time filtering false positives than reading real ones.
Use a classic tool. Gremlins.js for the browser, adb shell monkey for Android. Both are free, both are dumb-to-smart tier, and both will tell you honestly what that tier can and cannot find.
Use an AI agent. This is the brilliant-monkey tier, and it is where the technique finally does what it always promised. Our round-up of monkey testing tools covers the current field across all three tiers, including the free and open-source options.
If you want to see the difference in practice, the fastest path is our free CLI:
npm install -g @mtai/monkeytest-core
monkeytest run https://your-site.com
It crawls a few pages, works out what a user would try, tries it, and hands you back the bugs with screenshots. The step-by-step walkthrough covers what the output means and how to wire it into CI.
Monkey testing is unpredictable interaction applied at volume to find bugs your test plan never imagined. It comes in three tiers, and for most of its history only the bottom two were achievable — which is why it stayed a niche technique with a reputation for noise.
The top tier, the one that understands what your application is for, is now buildable. That does not make monkey testing a replacement for your test suite. It makes it a genuinely useful sweep across everything your test suite does not cover, which is most of your application.
Software Engineering Leader , Helping teams deliver quality software.
A practical round-up of monkey testing tools for web, mobile and code-level fuzzing — what each one actually finds, what it costs, and which ones are worth your afternoon.
TutorialsInstall the open-source MonkeyTest CLI, point it at a URL, and get a bug report with screenshots. Then wire it into CI so every pull request gets tested by an agent.
GuidesA step-by-step walkthrough for running your first intelligent monkey testing session with MonkeyTest AI and interpreting the results.