Arbitraging an MMO economy with a homemade price tracker
A game with a player-driven free market, an arbitrage seam, and no API to read it. So I built a pixel-by-pixel price reader, a bot fleet to feed it, and a nightly engine that told me what to buy and sell. At its peak I was sitting on about three billion in in-game currency.
The opportunity
As a student I played an MMO with a sprawling, player-run marketplace. People set their own prices, opened their own shops, even paid for extra listing visibility. A proper free market, and I was hooked: if you could see the prices move, you could buy low and sell high, with real in-game money on the table.
The whole opportunity is what happens when you line up one item across every shop selling it:
Reading a screen that didn’t want to be read
The game ran in its own desktop client. No browser, no API, nothing to intercept. I installed and configured at least five different OCR engines before admitting the fastest option was to write my own; I regret not starting there. Off-the-shelf OCR choked on the 9-pixel market font anyway. So I built my own reader: a fleet of game accounts saved a 77×11-pixel crop of each item’s best price, and a decoder thresholded the crop, sliced it into nine fixed digit cells, and read each digit through a hand-built decision tree that checks at most nine single pixels per cell. A “1” takes exactly one. The Java project’s real name is OdioGliOcr, “I hate OCRs”.
![]()
The machine around it
The reader was the middle of a pipeline that ran every night for about four and a half months, from autumn 2016 into February 2017:
- A dozen collector accounts (named Bread, Buff, Buy, Drop, Keep…) took turns searching the bazaar and screenshotting prices. The run logs read “ora raccolgo i prezzi”, “now I collect the prices”.
- Every crop became a row in a per-item CSV ledger: 33,292 readings across 193 items, from cheap consumables to the priciest gear in the game.
- A statistics pass computed an outlier-trimmed robust mean, plus 5/15/20-day windows and weekday and monthly means. A rule chain then issued Compra / Vendi verdicts, recorded which evidence fired, and routed the strong ones into
instaBuy.txtandinstaSell.txt, my morning shopping list.
![]()
It even drew charts for every item, straight out of 2017:
![]()
Rebuilt in the browser
In 2026 I dug the archive out and ported the tool’s logic to the browser, line for line. It isn’t a simulation: the page carries the real archived screenshots and the real price logs, and the port is verified against the archive. It re-decodes 1,677 stored crops into exactly the prices the tool logged in 2017, and a signal re-run “as of 10 Feb 2017, 18:00” reproduces the original’s final call for all 193 items, down to the flags each verdict fired and the means to the integer.
Runs entirely in your browser. Watch the pixel decoder work through real screenshots probe by probe, then scrub months of real market history while the buy/sell engine re-issues its verdicts. The game stays unnamed.
![]()
What the returns looked like
I bought the lows and sold the highs, and at one point I was sitting on about three billion in in-game currency. That number is meaningless without the mechanics: the most expensive items in the game ran around fifteen billion, and there was a real-money market for that kind of currency. Trading it for real cash would have been a heavy terms-of-service violation, so I stayed clear. Part of me still regrets not daring.
The trades that paid best usually came from other people’s mistakes. That felt more sad than funny.
The other thing I got out of it was a close look at how an economy behaves when the underlying resources are effectively infinite, as they are in most games: prices anchor to habit more than to scarcity, which makes each deviation an unusually honest signal.
Why it ended
Four and a half months in, the fun ran out. I’d solved it, and a game loses its charm when you have full knowledge over the rules and how to win. If I did it again, I’d automate the buying and selling as well. I think I might already have; I don’t fully remember.
Notes
Nobody asked me to build any of this. I just don’t like leaving a system unread, games included. The nightly pipeline lived in a class called ProbablyNotAgileAndAlsoDeprecated.java.