---
title: "Redistributing Billions in the Neopets Economy"
description: "A six-month reverse-engineering project on a Neopets shop, the duplication exploit that followed, and what I've come to understand about why I kept going."
publishedAt: 2026-07-03T00:00:00.000Z
tags: ["internet-history","reverse-engineering","security","engineering-ethics"]
canonical: https://danielmay.co.uk/posts/redistributing-billions-neopets/
---

<span id="introduction" class="anchor-top"></span>

> Over six months in 2014, a network of over 200 Neopets players ran software I made to record 48,000 snapshots of a single shop's inventory. We saw total item flow valued at over 6.5B Neopoints, built an autobuyer that generated roughly 167M NP in profit, before the project abruptly ended amid server instability due to a corporate transition. When the site returned, backend issues enabled game-breaking exploits: mass item duplication and "free NP". We abused those glitches to duplicate the game's most coveted items, donated billions to the <i>Money Tree</i>, and then released a script for the community to use. At the time, I thought of it as redistribution. Reflecting now, I think it was just a selfish attempt to be seen.

<nav class="toc-rail" aria-label="Table of contents">
  <div class="toc-post-title" aria-hidden="true">Redistributing Billions in the Neopets Economy</div>
  <ol>
    <li><a href="#introduction"><span class="toc-txt">Introduction</span></a></li>
    <li><a href="#detection-and-enforcement"><span class="toc-txt">Detection and Enforcement</span></a></li>
    <li><a href="#the-attic"><span class="toc-txt">The Attic</span></a></li>
    <li><a href="#restock-analysis"><span class="toc-txt">Restock Analysis</span></a></li>
    <li><a href="#purchasing"><span class="toc-txt">Purchasing</span></a></li>
    <li><a href="#an-abrupt-end"><span class="toc-txt">An Abrupt End</span></a></li>
    <li><a href="#exploit-discovery"><span class="toc-txt">Exploit Discovery</span></a></li>
    <li><a href="#robin-hood-or-so-i-thought"><span class="toc-txt">Robin Hood, or so I thought</span></a></li>
    <li><a href="#further-than-items"><span class="toc-txt">Further Than Items</span></a></li>
    <li><a href="#impact-and-reflections"><span class="toc-txt">Impact and Reflections</span></a></li>
    <li>
      <a href="#appendix"><span class="toc-txt">Appendix</span></a>
      <ol>
        <li><a href="#releasing-the-dataset"><span class="toc-txt">Releasing the dataset</span></a></li>
        <li><a href="#acknowledgements"><span class="toc-txt">Acknowledgements</span></a></li>
      </ol>
    </li>
  </ol>
</nav>

I started playing Neopets in 2003, and it was cutting edge for its time, competing with other online timesinks like [Newgrounds.com](https://www.newgrounds.com/) and early social networks. For me at least, it offered an eccentric mix of [Tamagotchi](https://en.wikipedia.org/wiki/Tamagotchi), [Miniclip](https://www.miniclip.com/) and [Drug Wars](https://en.wikipedia.org/wiki/Drug_Wars_(video_game)). The Neopets Team <i>("TNT")</i> made something really special.

Over time, though, I grew tired of the repetition. The giant omelette only gave away one piece per day, and other activities were "daily" gated. Searching for items on the <i>shop wizard</i> would lock you out if you spent too much time looking for a good deal. Unaware that these limitations were likely caused by bots, I asked the question *why can't this computer just play the game for me?*, and that led me to look online for cheats. Eventually, I built cheats of my own - not so much surfing the web as drifting between communities.

I wound up enveloped in a cheating/hacking community, researching and developing programs that automated Neopets. I learned how to engineer software by building autobuyers that spoofed browsers and tried to beat the competition, and then posted those programs on forums and MSN Messenger<sup class="fnref" id="fnref-1"><a href="#fn-1">1</a></sup>. Seeing something I produced delight other people was too addictive to ignore, even as it brushed against an ethical line I didn't yet understand.

And from that passion, I built a career. By 2014 I was 22, four years into building foreign exchange trading platforms in London, traveling to <i>tier one</i> banks to advise <i>Directors</i> on which technologies deserved their attention, surrounded by *real* engineers with *real* degrees. I was good at the job, but I still braced, most days, for someone to work out that I didn't belong there. I'd decided the Neopets stuff belonged to an earlier version of me that I'd grown out of, but still I ended up back there, partly because I think everything I built at work was in service of someone else's problem, and partly because of how it felt to be there. Nobody in that world knew or cared where or whether I'd gone to school. It was a place where I already belonged, where the only thing that counted was whether you could take a system apart, and I could. I wanted a problem of my own again: something unsolved, that would give way to the kind of attention that I was good at.

## Detection and Enforcement

Neopets' bot detection was always rudimentary, but TNT never held back on enforcement: once bot activity was detected, accounts were <i>frozen</i> (banned) immediately. Spoofing a browser was table stakes, and if you were a particularly naughty individual, they'd block by IP. This landscape created an arms race and incentivized widespread proxy use. My take is that they likely had a user base too large and activity too great to justify investing in analytics to enable better anti-cheat.

Unfortunately, this landscape *did* harm the player experience. Searching player-owned shops too quickly would lock you out until the next hour rolled around, and refreshing too frequently at an NPC shop risked receiving a similar multi-hour temp ban. Surprisingly early on, a custom captcha was added to the item purchase flow that asked the user to click a Neopet overlaid on a background:

<figure>
  <div class="image-row pair">
    <img src="https://danielmay.co.uk/posts/redistributing-billions-neopets/captcha-1.webp" alt="Neopets click-the-pet captcha: a Neopet overlaid on a busy background, the pet rendered as the darkest cluster of pixels" />
    <img src="https://danielmay.co.uk/posts/redistributing-billions-neopets/captcha-2.webp" alt="A second variant of the click-the-pet captcha with a different background, the pet again the darkest cluster of pixels" />
  </div>
  <figcaption>The now-defunct click-the-Neopet captcha. The pet is usually the darkest cluster of pixels.</figcaption>
</figure>

This wasn't much of a setback for the experienced programmers in the community. By choosing to layer a darker image on top of a lighter one, a simple loop finding the *darkest* 10x10 pixel cluster successfully identified the pet, most of the time:

```c
int darkest = 255, petX = 0, petY = 0;

for (int x = 0; x < w; x += 10)
    for (int y = 0; y < h; y += 10) {
        int b = brightness(x, y); // HSV value, 0-255
        if (b < darkest) { darkest = b; petX = x; petY = y; }
    }

click(petX, petY);
```

I imagine they might have been a bit disappointed to see a solve like this. Whichever dev shipped it did leave a little easter egg for us though: calls to `GET /captcha_show.phtml` were forced to supply a captcha identifier in a parameter ironically named `_x_pwned` - nice. This relic was [retired](https://www.jellyneo.net/?go=comments&post=15973) in June 2026, sadly.

## The Attic

<img class="medium" src="https://danielmay.co.uk/posts/redistributing-billions-neopets/almost-abandoned-attic.webp" alt="The Almost Abandoned Attic shop banner from Neopets" />

Over time, TNT continued to shape virtual economy features around bot protection. Some NPC shops, like the Igloo Garage Sale, sold rarer and higher value items, but were gated behind account age. I'd written a small autobuyer for that before, but there was something new to look into: <i>The Almost Abandoned Attic.</i>

The Attic had custom rules: it stocked the rarest items that wouldn't appear elsewhere, and only accounts over three years old were able to access it. My assumption is that TNT likely considered this a *"win-win"* - rewarding long-standing players with a special store and attacking the profitability of bots by increasing post-detection recovery time.

I was a little less interested in an autobuyer this time, though, and instead the custom rules stuck out to me. There were websites out there already like [JellyNeo's Item Database](https://items.jellyneo.net/) that captured the *market price* of items in the economy. But there had been no visible analysis into any of the algorithms behind *how* shops on Neopets restocked, instead simple automation that took advantage of *when* the good items showed up. Maybe it was random, but when considering the different behavior, maybe it wasn't. I thought: what if some kind of networked autobuyer could report aggregated restock telemetry for analysis?

- *How often does the shop restock? Is it regular, or is there a derivable pattern?*
  - *Can we lower our risk of detection by checking stock around a given time?*
- *Which items appear most frequently?*
  - *Can we selectively choose which restocks to target, knowing they may be more profitable?*
- *What impact does current stock have on restocks?*
  - *Does emptying the shop by buying unprofitable items trigger a different kind of behavior?*

I discussed the idea with friends in our forum's dedicated IRC channel, and quickly formed a collaborator partnership with an engineer in Germany. Together, we figured out a client/server architecture, with them handling a small analytics capture PHP backend writing to a MySQL database, and me handling the client, responsible for probing the shop, shipping the data and, eventually, buying the items. We both agreed that while buying items in the shop was the eventual goal, simply learning about the mechanics of the game was the driving curiosity at the start.

With our shared credibility in the community as badged *"programmers"*, we thought we might be able to convince other members to help. Like some kind of grey area community data collection project. This was the first place I could have been more honest with myself: the questions were interesting, but they were always going to be abuse-adjacent.

## Restock Analysis

The client started as a browser extension but evolved to a Windows client written in C#. PHP's flexibility on the backend made it easy for us to spin up a little website that reported on the latest restocks and incentivized contributors with a leaderboard.

We saw an initial spike of adoption from eager helpers in late March, so this let me dig straight into modelling the data in Excel. The first few hours of data helped confirm a community theory around a regular restock interval: restocks appeared to cluster around a seven-minute interval. Looking at all of the data now, it's even clearer:

The shop didn't necessarily restock *every* `7m2.75s`, but after a restock occurred, it would only ever potentially happen on a subsequent `7m2.75s` metronomic tick. This was useful, though narrow, as we were hoping to derive better insights earlier.

It did allow us to design around refresh-frequency-based ban detection. If we could narrow down the *possible* minutes in an hour in which the shop *could* restock, we would be able to dramatically reduce the amount of our detectable activity, likely to below that of even a regular player. That same logic could also inform our purchasing algorithm to catch items faster than others, and we didn't really worry about traffic patterns or fingerprinting on such a small scale.

In May, activity dropped, and it became worryingly clear that we weren't going to get many more insights out of the data we had beyond the relationship to `7m2.75s`. Despite capturing item value flow of over 3B NP, and seeing restocks for coveted items like <i>Bony Grarrl Club</i> (130M) and <i>Sticky Snowflake Stamp</i> (150M), these facts only frustrated members as they sat out of reach. We knew that purchasing had to come soon if we wanted to learn more, so in June, we started work. This was the moment the project crossed over from observation into extraction.

## Purchasing

Considering the `7m2.75s` interval pattern, with the client-server architecture we'd built, and the adoption we'd seen, we had several options. In theory, we could have stored the most recently seen restock on the server and coordinated many clients across geographies to all refresh `7m2.75s` afterwards, maybe even forcing them to hammer the same item. But this project was meant to be a curiosity-driven data collection effort, not a domain-specific botnet designed to squeeze *all* of the fun out of the game. Many contributors didn't even really play the game anymore.

With that in mind, the resulting algorithm was conservative by cheating standards. We waited a fixed six-minute period after detecting a restock successfully, and never shot out requests without a healthy randomly sampled delay. Despite that, our network purchased more than 2,000 items in just six weeks, generating ~167M NP gross profit. I suppose you could say we operated some kind of Neopets hedge fund.

## An Abrupt End

In mid-September 2014, Neopets servers began encountering major issues associated with a corporate transition to Jumpstart, who had purchased the company from Viacom earlier that year. At exactly 11:12 <i>Neopian Standard Time</i> on September 17 2014, the Attic restocked for the final time, eerily visible from our user probes:

And just like that, the analysis that hundreds of us had worked on for half a year was unceremoniously fragged. Over six months, we saw a million items flow through that shop, worth an estimated 6.5B neopoints.

## Exploit Discovery

Soon after the site returned, many features were broken entirely, and IRC began to murmur about instability. There were reports of odd activity happening here and there - game state wasn't being persisted as players expected it should. In one channel, someone said something about losing an item that they had put into their <i>Safety Deposit Box</i>. The engineers in the community quietly wondered if there was a way to take advantage. My curiosity grew.

I started some crude in-browser investigation with random items on an account: holding down the space bar on the "submit" button, hoping to possibly see more than one item appear on the other end. It took some time, but eventually sure enough, there it was:

<img src="https://danielmay.co.uk/posts/redistributing-billions-neopets/item-dupe-race.webp" alt="Inventory showing the same item credited more than once after rapidly resubmitting, evidence of a race condition" style="max-width: 504px" />

Wow. Was that right? Simply hammering the submit button could cause some kind of race condition<sup class="fnref" id="fnref-2"><a href="#fn-2">2</a></sup> that credits the item more than once? It's that simple? That immediately challenged years of assumptions that rudimentary attack surfaces were well-covered.

I have regrets about my next steps, but I think it's important to state that at the time, I saw distinctions and built a justification:

1. Privately duplicating items for personal gain risked causing more economic harm and *hiding bugs*, so:
2. Publishing the method for everyone to take advantage of was *equality among cheaters,* and
3. Giving away coveted (duplicated) items for free is me being <i>Robin Hood</i>

And doing that would be fine, because I didn't stand to gain financially from the project, right? There were, of course, players selling NP and even stolen accounts, and this was surely much better than that. Calling it <i>redistribution</i> warped the narrative and pushed an already slipping boundary even further. It helped abstract away the damage and give me a seemingly heroic central role, wrongly.

But I didn't see that at the time, and went on to write a simple <i>exploit</i> script, and shared it with friends:

<figure>
  <img src="https://danielmay.co.uk/posts/redistributing-billions-neopets/glitch-suite-demo.webp" alt="Animated demo of the glitch suite script duplicating items automatically" />
  <figcaption>The script I distributed to other cheaters.</figcaption>
</figure>

## _Robin Hood_, or so I thought

The rarest and most valuable item in Neopets was the <i>Super Attack Pea</i>, a multi-use Battledome weapon worth 1 billion Neopoints. It was the strongest battle item in the game, capable of inflicting the most damage, and fewer than ten were estimated to be in circulation. User shops could only price items to a maximum of `99,999 NP`, and in order to duplicate an item worth 1B NP, we needed access to at least one. I reached out to the wealthy cheaters I knew in the community. Soon enough, I found someone, their single pea (with several hundred of millions NP collateral, because this was *serious*) and then I subsequently stocked a thousand dupes in my shop, effectively free:

<img src="https://danielmay.co.uk/posts/redistributing-billions-neopets/super-attack-pea-dupes.webp" alt="A user shop stocked with a thousand duplicated Super Attack Peas, each priced at the maximum" />

Absurdly I found users with a plushie version of the pea on the <i>Trading Post</i> and offered them a free 1B upgrade:

<img class="medium" src="https://danielmay.co.uk/posts/redistributing-billions-neopets/pea-plushie-upgrade-offer.png" alt="A Trading Post exchange offering a real Super Attack Pea in return for a plushie version, a free 1B upgrade" />

I would then go on to donate thousands of high-value items to the <i>Money Tree</i>, a place usually only reserved for giving poor players junk you don't want. At this point, I wasn't really thinking about the economic impact. I remember thinking *"Players suddenly have access to items they'd never had the chance to play with before, that's good right? The game was getting on, past its peak, what's the worst that could happen?"*

## Further Than Items

More investigation quickly showed that it was possible to hammer bank deposits/withdrawals to generate Neopoints directly. Eventually, I managed to overflow on-hand NP:

<figure>
  <img class="medium" src="https://danielmay.co.uk/posts/redistributing-billions-neopets/np-overflow.webp" alt="A Neopets account balance showing 2,147,483,647 Neopoints, the signed 32-bit integer maximum" />
  <figcaption><i>2,147,483,647 is the maximum value for a 32-bit signed integer.</i></figcaption>
</figure>

Everything suddenly felt pointless. All of that excitement blinded me to something simple: rules aren't the obstacle to the game, they define the game.

Soon after, the site was taken offline. I don't know whether the bank exploit contributed to that decision or whether it resulted from the broader instability, but I remember being glad then, and I'm glad now. The damage was now done, and despite widespread expectations from the community, there was no rollback. The market now had to move forward, and TNT tried their best to clean up the damage.

## Impact and Reflections

The economic impact was vast and was well covered by [Alex Irpan](https://www.alexirpan.com/2018/11/10/neopets-economy.html) as well as on [Reddit](https://www.reddit.com/r/neopets/comments/8wyqpl/neopets_history_the_2014_dday_dupe_day/). By 2018, the price of a <i>Super Attack Pea</i> had fallen by 75% to 250M, but an [article from 2024](https://www.thegamer.com/neopets-best-battledome-items/) says the price has now started to climb back up to near 450M. The <i>Attic</i> never returned<sup class="fnref" id="fnref-3"><a href="#fn-3">3</a></sup>, and several other game features were turned off entirely for months or years after the core races were fixed.

I have a complicated relationship with the way I learned software engineering. Reverse engineering Neopets taught me to observe systems, test assumptions and build tools that people wanted to use. It also taught me that capability and permission are two different things. Information [may want to be free](https://en.wikipedia.org/wiki/Information_wants_to_be_free), but that doesn't mean it's my job to liberate it.

I think it's important to reflect on the slow growth of the project. While the duplication bug was the most impactful, it was just one revelation in a situation where the line had already been moving for months. I justified each step, and soon enough what I had first framed as a benign data-collection project had gradually become an abuse system that risked harming people and businesses I cared about. Was that the notoriety I really wanted? No.

It's been twelve years since, and I've had a lot of time to reflect on *why* I pushed those boundaries. I told myself I just wanted to understand: the captcha, the restock, the race condition - and it sounded honest. But there was never innocence underneath that curiosity. I had an audience, and understanding the system was how I held their attention. Each thing I figured out was something to be *seen* as figuring out, or represented social capital to be won, or a chance to be the *only one* who understood. I was thinking about notoriety and never stopped to think about the scale or impact my actions could have on a game I'd enjoyed for so many years. Now I see that *wanting to understand* and *wanting to be seen* were two faces of the same desire: to display competence during insecurity. I was just hiding behind the more respectable of the two. I wasn't <i>Robin Hood</i>. I was someone who found an audience that rewarded me for being clever, and who kept being clever at the expense of a game, and the people who played it. And unfortunately, I kept at it long past the point when the clever move would have been to stop.

<section class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn-1">I imagine the modern equivalent is a kid out there working on a sneaker autobuyer and maybe advertising it to their friends on their Instagram story. Since I got started, online economies and opportunities for profit have both changed and stayed the same in a funny way. <a href="#fnref-1" class="fn-back" aria-label="Back to reference 1">↩</a></li>
    <li id="fn-2">A flaw of this kind can occur when a state-changing operation isn't atomic or correctly idempotent, explained well on the <a href="https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use">"Time-of-check to time-of-use" wiki page</a>. No post-mortem was ever provided, so we may never get an insight into what was happening behind the scenes. <a href="#fnref-2" class="fn-back" aria-label="Back to reference 2">↩</a></li>
    <li id="fn-3">Neopets did re-use the shopkeeper character for a Mobile thing in 2022, nine years later. <a href="#fnref-3" class="fn-back" aria-label="Back to reference 3">↩</a></li>
  </ol>
</section>

---

## Appendix

### Releasing the dataset

I've preserved the original historical restock dataset and I'm reviewing whether a safely deidentified version can be released on Hugging Face. Perhaps someone else can determine if there ever was an underlying pattern to the restock algorithm, or maybe one day someone can wire it into their Neopets emulator?

### Acknowledgements

Users running my script were told about the risks of getting their accounts frozen for duplicating items, but there might have been collateral damage to innocent accounts simply for receiving or handling duplicated items. If that was you, I'm sorry.

Thanks to my friends for reading early versions of this post and providing feedback.

The <i>Attic Restock Analysis</i> project wasn't possible without my anonymous collaborator, who I'm proud to say has now enjoyed a successful engineering career! I'm also grateful to the contributors who gave their data to the project, especially those who assisted before purchasing was enabled.

I also want to say thank you to the hundreds of staff at TNT who put their passion and energy into Neopets for so many years. I'm sorry for making your job harder.