Bots Enumerating Discount Codes at Checkout
Brute forcing promo codes is quiet, cheap, and visible in your logs if you know the pattern: rapid failed code attempts, dictionary sequences, and why rate limits on the code field matter.
Discount code fields accept guesses, and bots make a lot of them. The pattern is called enumeration: thousands of attempts cycling through likely codes, seasonal words, brand names with numbers, leaked code formats, until one returns a discount. Each attempt costs the bot nothing. A successful guess costs the store the margin on every order the code is then shared for.
This traffic hides in a blind spot. It is not login traffic, so credential stuffing defences do not watch it. It is not scraping, so it does not look like catalogue abuse. It lives at checkout, in the apply code endpoint, generating failure after failure that most stores never graph.
The log signature
Look for sessions or addresses applying many distinct codes with a near total failure rate, attempts arriving at machine regular intervals, and code strings that follow a logic: word lists, year and season combinations, staff style and influencer style formats your own marketing uses. Human shoppers mistype a code once or twice and then go and check their email. Nobody human tries forty codes in ninety seconds.
Also watch the successes in context. A code that had no redemptions suddenly redeeming from many new customers in a day may have been enumerated and posted, or simply leaked, and the response differs, but the detection starts in the same place: redemption and attempt data reviewed together. Stores that only review redemptions see the fire. The attempt log shows the arsonist's earlier visits.
Why codes are guessable, and how to make them less so
Human friendly codes are bot friendly codes. A store's public codes follow patterns by design, because customers must remember and type them, and any pattern a customer can predict, a script can enumerate. The structural answers are unglamorous: make private and influencer codes long and random rather than name based, single use where the economics allow, capped in total redemption, and set to expire when the campaign ends rather than drifting on forever. A leaked or guessed code with a redemption cap is a contained loss. An uncapped evergreen code is an open one.
On the field itself, apply rate limits and progressive friction to repeated failed attempts from a session, the same discipline used on login forms. A shopper with a genuine code needs one or two attempts. The tenth failed attempt in a minute can meet a delay or a challenge without any legitimate customer ever noticing the rule exists.
Separate the sharing problem from the guessing problem
Not every abused code was enumerated. Codes get posted to coupon sites within hours of an email going out, by real customers, and that is a distribution decision to manage with terms, caps, and unique codes, not a bot problem. Conflating the two produces bad defences: heavy friction at checkout that punishes ordinary shoppers for a leak that happened in an inbox. The logs distinguish them if you look. Enumeration shows attempts before the success. Sharing shows successes with no attempt pattern at all. Read the traffic for which problem you actually have before buying the cure for the other one.
Related reading
If this topic is useful, these earlier guides go deeper on connected questions: Headless Browser Traffic: Signs Worth Checking in Server Logs, Bots Scraping Product Images and Copy for Counterfeit Listings, and Not All Bots Are Waste: Separating Search Crawlers and Monitoring From Scraping.
Frequently asked questions
What is discount code enumeration?
Automated guessing of promo codes at checkout: bots cycle through word lists, seasonal terms, and a store's own code formats until an attempt returns a valid discount.
How do you spot code enumeration in logs?
Many distinct codes attempted by one session or address with near total failure, at machine regular intervals, using strings that follow a pattern. Humans mistype once or twice and stop.
How can stores make codes harder to guess?
Long, random codes for private and influencer use, single use where possible, redemption caps, and real expiry dates, plus rate limits and progressive friction on repeated failed attempts at the field.
Is every abused code a bot problem?
No. Codes are also shared by customers to coupon sites. Sharing shows redemptions without an attempt pattern; enumeration shows the attempt pattern first. The fixes are different, so diagnose before defending.