Zero to Open Poker Leaderboard in 7 Days: A Daily Plan
You can take a poker bot from "doesn't exist" to "ranked on the Open Poker leaderboard" in 7 days. Not 7 weeks. The platform is built so a developer can register, connect, and play on day 1, then add one strategy upgrade per day until they're competitive. Here's the plan we recommend, with the exact upgrades that move the needle and the ones that don't.
Why does the 7-day plan work?
Because each day adds a single, isolated improvement on top of a working bot. You're not building a system end-to-end before the first hand. You're shipping a calling station on day 1 and improving it incrementally. By day 7, every upgrade has been validated against real opponents, not against a self-play simulator that lies to you.
This is the opposite of how most bot projects fail. Most developers spend two weeks designing a "complete" architecture, then realize on day 14 that their hand evaluator doesn't match the protocol's card format, or their action sender forgets the turn token, or their pot odds calculator uses the wrong field. The 7-day plan defers all of that until the bot is already running.
The other reason it works: Open Poker's leaderboard rewards volume more than peak skill. A mediocre bot that runs 7 days outscores a brilliant bot that runs 1 day. By day 7 you have 4-5 days of accumulated hand history, which is enough variance reduction to climb above the bottom of the field even if your strategy is still rough.
Day 1: Get a calling station running
Your only goal on day 1 is a connected bot that plays legal hands. Don't worry about strategy. Don't worry about profits. Don't worry about anything except: bot connects, bot joins table, bot responds to your_turn with a valid action, bot doesn't crash for 30 minutes.
Use the build a poker bot in Python guide as your starting point. The full bot is under 50 lines. Copy it, paste your API key, run it. You'll see "Connected as YourBotName" within 30 seconds and your first hand within a minute or two of joining the lobby.
The calling station strategy (check if you can, otherwise call, otherwise fold) loses chips but it produces complete event loops. Every message type gets handled. Every action gets sent with a valid turn token. By the end of day 1 your bot has played 50-100 hands and you have a baseline win rate to improve.
End-of-day target: bot has played at least 20 hands, no crashes, no timeouts.
Day 2: Add pre-flop hand selection
The single biggest improvement you can make on top of the calling station. Most starting hands in Hold'em are losers; folding the bottom 60% pre-flop dramatically reduces the chips you bleed on the flop and beyond.
def should_play_preflop(cards):
"""Top ~40% of starting hands."""
ranks = "23456789TJQKA"
r1 = ranks.index(cards[0][0])
r2 = ranks.index(cards[1][0])
high, low = max(r1, r2), min(r1, r2)
pair = r1 == r2
suited = cards[0][1] == cards[1][1]
if pair: return True
if high >= 10: return True
if high >= 8 and suited: return True
if high == 12 and low >= 7: return True
return FalseStore the hole cards when hole_cards arrives. On your_turn, if it's preflop and should_play_preflop() returns False, fold. Otherwise fall back to the calling station logic.
This single change typically takes a calling station from -2.5 bb/100 to about -0.8 bb/100. You're still losing chips, but you're losing them at a rate that doesn't trigger frequent rebuys. End-of-day target: 200+ hands played, win rate above 12%.
Day 3: Add pre-flop raising
The day 2 bot folds the bad hands but never raises the good ones. Opponents see free flops against your premium holdings, which means they get to make hands that beat you. Fix: raise your top 15% of hands instead of just calling.
def should_raise_preflop(cards):
ranks = "23456789TJQKA"
r1, r2 = ranks.index(cards[0][0]), ranks.index(cards[1][0])
pair = r1 == r2
high, low = max(r1, r2), min(r1, r2)
suited = cards[0][1] == cards[1][1]
# Premium pairs
if pair and r1 >= 8: return True # 99+
# Big aces
if high == 12 and low >= 9: return True # AT+
# Suited broadway
if suited and high >= 10 and low >= 9: return True
return FalseWhen this returns True and raise is in valid_actions, send a min-raise instead of just calling. The amount field is the raise-to total, not an increment. Use the min value from the raise action entry as your amount.
End-of-day target: 400+ hands played, win rate above 16%, bb/100 approaching break-even.
Day 4: Add pot odds for postflop calls
Postflop is where bots leak the most chips. Calling random bets without doing the math is what makes a calling station a calling station. Fix it with pot odds.
The math: divide the call amount by the pot after your call. If your estimated win probability exceeds that ratio, call. Otherwise fold. The poker math for bots tutorial covers the formula in detail.
def call_is_profitable(your_turn_msg, win_pct=0.30):
actions = {a["action"]: a for a in your_turn_msg["valid_actions"]}
if "call" not in actions:
return False
pot = your_turn_msg["pot"]
call_amt = actions["call"]["amount"]
if call_amt == 0:
return True
pot_odds = call_amt / (pot + call_amt)
return win_pct > pot_oddsFor day 4, use a flat 30% win rate estimate. It's wrong on most specific spots, but on average it's a much better default than "always call." You'll fold rivers where you have nothing and continue with hands that have realistic equity.
End-of-day target: 600+ hands played, bb/100 breaking even or slightly positive.
Day 5: Track opponent VPIP
Day 5 is when you stop playing every hand the same and start adapting to the table. Build a simple opponent tracker that logs how often each player puts chips in pre-flop. The opponent modeling guide has the full implementation, but a minimum viable version:
from collections import defaultdict
vpip_data = defaultdict(lambda: {"hands": 0, "voluntary": 0})
acted_this_hand = set()
def on_hand_start():
acted_this_hand.clear()
def on_player_action(msg):
name = msg.get("name", f"seat{msg['seat']}")
if msg["action"] in ("call", "raise", "all_in"):
if name not in acted_this_hand:
vpip_data[name]["hands"] += 1
vpip_data[name]["voluntary"] += 1
acted_this_hand.add(name)
def get_vpip(name, default=0.25):
data = vpip_data[name]
if data["hands"] < 20:
return default
return data["voluntary"] / data["hands"]Use VPIP to adjust your raising range. Against an opponent with VPIP under 15% in late position, expand your stealing range. Against an opponent with VPIP over 50%, only value-bet (don't bluff: they call too much).
End-of-day target: 800+ hands, bot is identifying at least 5 distinct opponents.
Day 6: Add bet sizing variation
Static bet sizing is the next leak. Most beginner bots either always min-raise or always pot-bet. Both are wrong. Mix three sizes based on the situation:
| Spot | Size | Reasoning |
|---|---|---|
| Pre-flop open from late position | 2.5x BB | Standard open, balances steal frequency with value |
| Continuation bet on dry board | 33% pot | Cheap, gets weak hands to fold |
| Value bet on wet board | 75% pot | Charges draws, builds the pot for value |
Compute your raise amount based on the spot, clamp to the min/max from valid_actions, and send. Mixing sizes makes you noticeably less exploitable. Opponents who track patterns can no longer guess your hand strength from your bet size alone. The betting strategy tutorial has the full breakdown.
End-of-day target: 1,000+ hands, bb/100 measurably positive, top 50% of leaderboard.
Day 7: Run uptime, monitor, iterate
Day 7 isn't about new features. It's about running your bot for 12+ hours straight, watching the leaderboard, and patching whatever breaks. The debug guide covers the most common failure modes (auth issues, timeouts, race conditions).
Three things to check:
1. Crash log. Wrap your main loop in a try/except that logs every exception with a timestamp. Run for 4 hours, then read the log. Fix the most frequent error first.
2. Slow decisions. Add latency logging from the timeout guide. Anything over 1 second deserves investigation.
3. Win rate by hour. Group your hand history by hour of the day and check if your win rate varies. Some bots win during peak hours (more opponents = more weak players to exploit) but lose at off-peak times. Use this to decide when to keep your bot running.
End-of-day target: Bot has played 1,500+ hands across the 7 days, ranks in the top 25% of the current season leaderboard, and runs unattended for 12+ hours without intervention.
What does the 7-day progression actually look like?
Here's the rough win-rate trajectory we've seen across multiple developers who followed this plan:
| Day | Strategy added | Median bb/100 | Hands by EOD |
|---|---|---|---|
| 1 | Calling station | -2.5 | 50 |
| 2 | Pre-flop fold range | -0.8 | 200 |
| 3 | Pre-flop raise range | -0.3 | 400 |
| 4 | Pot odds postflop | +0.4 | 600 |
| 5 | VPIP-based opponent reads | +1.1 | 800 |
| 6 | Bet sizing variation | +1.7 | 1,000 |
| 7 | Stability and uptime | +1.7 | 1,500+ |
The biggest jumps are days 2 and 5: pre-flop hand selection and opponent modeling. These are the cheapest improvements per line of code. Days 4 and 6 are smaller gains but they compound nicely. Day 7 doesn't add edge, but it converts the edge you already have into a leaderboard position by accumulating hands.
This isn't a rigorous study. Variance at 6-max is high and individual results vary by the season's player pool, but directionally the pattern is consistent: simple upgrades stack into a competitive bot in less than a week of part-time work.
What should you NOT do in the first week?
Three traps to avoid.
Don't write a hand evaluator from scratch. It's tempting because it feels like the "real" poker work. It's a multi-day project that adds no measurable edge over a simple win-probability heuristic. If you absolutely need hand strength, use PokerKit or Treys (Python libraries with battle-tested evaluators) instead of writing your own. We use PokerKit on the server side for the same reason.
Don't try to implement CFR or GTO solving. Counterfactual Regret Minimization is the technique behind Pluribus and Libratus. It's also a multi-month research project that requires tens of millions of training hands. For a first bot, you'll get better results by spending the same time on basic heuristics. Add CFR later if you want to push past the top 20%.
Don't deploy on day 1 with no error handling. Wrap your event loop in a try/except, log every exception, and keep going. Bots that crash on a single bad message lose all the table time they would have accumulated overnight. The fix is one try/except block.
What comes after day 7?
Once you have a working competitive bot, the next round of upgrades are incremental and high-impact:
- Position-aware ranges: tighter under the gun, looser in the cutoff and button
- Multi-street planning: think about what you'll do on the turn before you bet the flop
- Bluff selection: pick boards where bluffs are credible (high cards, fewer draws)
- Bankroll management: vary your buy-in based on session results
Each of these adds another 0.5-1.5 bb/100 if implemented well. The path to top-10 leaderboard finishes isn't a single breakthrough; it's stacking 10 small improvements until your bot has a measurable edge in every common spot. The full platform docs cover every protocol detail you'll need for the next round.
FAQ
How long does it really take to build a competitive poker bot? For a first competitive bot (top 25% of the leaderboard), 7 days of part-time work is realistic. For top 10% you should expect 2-4 weeks of iteration and tuning. Top 1% requires CFR-style algorithms, opponent profiling at scale, and months of refinement.
Can I follow this plan with a language other than Python?
Yes. The protocol is pure WebSocket plus JSON, so any language with WebSocket support works. JavaScript, Go, Rust, Java, C++, even Bash with websocat have all been used to build bots on Open Poker. The Python examples translate directly.
How many hands do I need to play to climb the leaderboard? You need at least 10 hands to appear on the leaderboard at all. To climb significantly, plan for 1,000-2,000 hands across the season. More hands reduces variance and lets your edge show through.
Do I need a Pro account to run this plan? No. Everything in this plan works on a free account. The Pro tier ($5/season, with bundle discounts) adds analytics, custom strategies, and shorter rebuy cooldowns, but the strategy upgrades themselves are free. See the Pro feature comparison for the full list.
What if my bot busts out before I finish the plan?
Auto-rebuy handles it. Send {"type": "set_auto_rebuy", "enabled": true} once after connecting and the server will automatically rebuy you (subject to a 5-minute cooldown on the free tier) when your bot busts. Your event loop keeps running and the next hand starts as soon as the cooldown expires.
Seven days of focused work is enough to take a poker bot from zero to leaderboard contender on Open Poker. The platform is designed for this iteration speed. Register a bot, follow the day-by-day plan, and you'll have a ranked entry by next week.