pip install roboat
pip install "roboat[async]" # async support via aiohttp
pip install "roboat[all]" # everything + test toolsfrom roboat import RoboatClient
client = RoboatClient()
# User lookup
user = client.users.get_user(156)
print(user)
# Builderman (@builderman) ✓ [ID: 156]
# Game stats
game = client.games.get_game(2753915549)
print(f"{game.name} — {game.visits:,} visits | {game.playing:,} playing")
# Catalog search
items = client.catalog.search(keyword="fedora", category="Accessories", sort_type="Sales")
for item in items:
print(f"{item.name} — {item.price}R$")roboat
# or: python -m roboat ____ _ _ _ ____ ___
| _ \ ___ | |__ | | _____ __/ \ | _ \_ _|
| |_) / _ \| '_ \| |/ _ \ \/ / _ \ | |_) | |
| _ < (_) | |_) | | (_) > < ___ \| __/| |
|_| \_\___/|_.__/|_|\___/_/\_/_/ \_|_| |___|
roboat v2.1.0 — roboat.pro — type 'help' to begin
» start 156
» auth
» game 2753915549
» inventory 156
» rap 156
» likes 2753915549
» friends 156
roboat uses Roblox OAuth 2.0 — no cookie extraction, no browser DevTools.
from roboat import OAuthManager, RoboatClient
manager = OAuthManager(
on_success=lambda token: print("✅ Authenticated!"),
on_failure=lambda err: print(f"❌ Failed: {err}"),
timeout=120,
)
token = manager.authenticate() # opens browser, 120s countdown
if token:
client = RoboatClient(oauth_token=token)
print(f"Logged in as {client.username()}")In the terminal, type auth. A browser window opens, you log in, and you're done. A live 120-second countdown is shown while waiting.
roboat/
├── roboat/ Source package (35 modules)
│ ├── utils/ Cache, rate limiter, paginator
│ └── *.py All API modules
├── examples/ 8 ready-to-run example scripts
├── tests/ Unit tests — no network required
├── benchmarks/ Performance benchmarks
├── docs/ Architecture, endpoints, models, FAQ
├── tools/ CLI utilities (bulk lookup, RAP snapshot, game monitor)
├── integrations/ Discord bot, Flask REST API
├── typestubs/ .pyi type stubs for IDE autocomplete
├── scripts/ Dev scripts (env check, stub generator)
└── .github/ CI/CD workflows, issue templates
from roboat import RoboatClient, ClientBuilder
# Simple
client = RoboatClient()
# Builder — full control
client = (
ClientBuilder()
.set_oauth_token("TOKEN")
.set_timeout(15)
.set_cache_ttl(60) # cache responses for 60 seconds
.set_rate_limit(10) # max 10 requests/second
.set_proxy("http://proxy:8080")
.build()
)import asyncio
from roboat import AsyncRoboatClient
async def main():
async with AsyncRoboatClient() as client:
# Parallel fetch — all at once
game, votes, icons = await asyncio.gather(
client.games.get_game(2753915549),
client.games.get_votes([2753915549]),
client.thumbnails.get_game_icons([2753915549]),
)
# Bulk fetch 500 users — auto-chunked into batches of 100
users = await client.users.get_users_by_ids(list(range(1, 501)))
print(f"Fetched {len(users)} users")
asyncio.run(main())from roboat import RoboatCloudClient
cloud = RoboatCloudClient(api_key="roblox-KEY-xxxxx")
cloud.datastores.set(universe_id, "PlayerData", "player_1", {"coins": 500})| API | Endpoint | Methods |
|---|---|---|
| Users | users.roblox.com |
7 |
| Games | games.roblox.com |
15 |
| Catalog | catalog.roblox.com |
8 |
| Groups | groups.roblox.com |
22 |
| Friends | friends.roblox.com |
11 |
| Thumbnails | thumbnails.roblox.com |
7 |
| Badges | badges.roblox.com |
4 |
| Economy | economy.roblox.com |
5 |
| Presence | presence.roblox.com |
3 |
| Avatar | avatar.roblox.com |
5 |
| Trades | trades.roblox.com |
7 |
| Messages | privatemessages.roblox.com |
7 |
| Inventory | inventory.roblox.com |
8 |
| Develop | develop.roblox.com |
14 |
| DataStores | apis.roblox.com/datastores |
7 |
| Ordered DS | apis.roblox.com/ordered-data-stores |
5 |
| Messaging | apis.roblox.com/messaging-service |
3 |
| Bans | apis.roblox.com/cloud/v2 |
4 |
| Notifications | apis.roblox.com/cloud/v2 |
3 |
| Asset Upload | apis.roblox.com/assets |
5 |
user = client.users.get_user(156)
users = client.users.get_users_by_ids([1, 156, 261]) # up to 100 at once
users = client.users.get_users_by_usernames(["Roblox", "builderman"])
page = client.users.search_users("builderman", limit=10)
page = client.users.get_username_history(156)
ok = client.users.validate_username("mycoolname")game = client.games.get_game(2753915549)
game = client.games.get_game_from_place(6872265039)
visits = client.games.get_visits([2753915549, 286090429]) # {id: count}
votes = client.games.get_votes([2753915549])
servers = client.games.get_servers(6872265039, limit=10)
page = client.games.search_games("obby", limit=20)
page = client.games.get_user_games(156)
page = client.games.get_group_games(2868472)
count = client.games.get_favorite_count(2753915549)group = client.groups.get_group(7)
roles = client.groups.get_roles(7)
role = client.groups.get_role_by_name(7, "Member")
members = client.groups.get_members(7, limit=100)
is_in = client.groups.is_member(7, user_id=156)
# Management (auth required)
client.groups.set_member_role(7, user_id=1234, role_id=role.id)
client.groups.kick_member(7, user_id=1234)
client.groups.post_shout(7, "Welcome everyone!")
client.groups.accept_all_join_requests(7) # accepts ALL pending
client.groups.pay_out(7, user_id=1234, amount=500)from roboat.marketplace import MarketplaceAPI
market = MarketplaceAPI(client)
# Full limited data — RAP, trend, remaining supply
data = market.get_limited_data(1365767)
print(f"{data.name} RAP: {data.recent_average_price:,}R$ Trend: {data.price_trend}")
# Profit estimator — includes Roblox 30% fee
profit = market.estimate_resale_profit(1365767, purchase_price=12000)
print(f"Net profit: {profit.estimated_profit:,}R$ ROI: {profit.roi_percent}%")
# Find underpriced limiteds (below 85% of RAP)
deals = market.find_underpriced_limiteds([1365767, 1028606, 19027209])
# RAP tracker — snapshot and diff over time
tracker = market.create_rap_tracker([1365767, 1028606])
tracker.snapshot()
# ... wait some time ...
tracker.snapshot()
print(tracker.summary())from roboat.social import SocialGraph
sg = SocialGraph(client)
mutuals = sg.mutual_friends(156, 261)
is_following = sg.does_follow(follower_id=156, target_id=261)
snap = sg.presence_snapshot([156, 261, 1234])
online_ids = sg.who_is_online([156, 261, 1234])
nodes = sg.most_followed_in_group([156, 261, 1234]) # parallel fetch
suggestions = sg.follow_suggestions(156, limit=10)API_KEY = "roblox-KEY-xxxxx"
UNIVERSE = 123456789
# DataStores
client.develop.set_datastore_entry(UNIVERSE, "PlayerData", "player_1", {"coins": 500}, API_KEY)
client.develop.get_datastore_entry(UNIVERSE, "PlayerData", "player_1", API_KEY)
client.develop.increment_datastore_entry(UNIVERSE, "Stats", "deaths", 1, API_KEY)
client.develop.list_datastore_keys(UNIVERSE, "PlayerData", API_KEY)
# Ordered DataStores (leaderboards)
client.develop.list_ordered_datastore(UNIVERSE, "Leaderboard", API_KEY, max_page_size=10)
client.develop.set_ordered_datastore_entry(UNIVERSE, "Leaderboard", "player_1", 9500, API_KEY)
# MessagingService — reaches all live servers instantly
client.develop.announce(UNIVERSE, API_KEY, "Double XP starts now!")
client.develop.broadcast_shutdown(UNIVERSE, API_KEY)
# Bans
client.develop.ban_user(UNIVERSE, 1234, API_KEY, duration_seconds=86400,
display_reason="Temporarily banned.")
client.develop.unban_user(UNIVERSE, 1234, API_KEY)from roboat import SessionDatabase
db = SessionDatabase.load_or_create("myproject")
db.save_user(client.users.get_user(156))
db.save_game(client.games.get_game(2753915549))
db.set("tracked_ids", [156, 261, 1234])
val = db.get("tracked_ids")
print(db.stats())
# {'users': 10, 'games': 5, 'session_keys': 3, 'log_entries': 42}
db.close()from roboat import EventPoller
poller = EventPoller(client, interval=30)
@poller.on_friend_online
def on_online(user):
print(f"🟢 {user.display_name} came online!")
@poller.on_new_friend
def on_friend(user):
print(f"🤝 New friend: {user.display_name}")
poller.track_game(2753915549, milestone_step=1_000_000)
@poller.on("visit_milestone")
def on_milestone(game, count):
print(f"🎉 {game.name} hit {count:,} visits!")
poller.start(interval=30) # background thread# Bulk user lookup → CSV or JSON
python tools/bulk_lookup.py --ids 1 156 261 --format csv
python tools/bulk_lookup.py --usernames Roblox builderman --format json
# RAP snapshot and diff
python tools/rap_snapshot.py --user 156
python tools/rap_snapshot.py --user 156 --diff # compare to last run
# Live game monitor with milestone alerts
python tools/game_monitor.py --universe 2753915549 --interval 60
# Environment health check
python scripts/check_env.py
# Generate .pyi type stubs
python scripts/generate_stub.py| Integration | File | Description |
|---|---|---|
| Discord Bot | integrations/discord_bot.py |
Slash commands: /user, /game, /status |
| Flask REST API | integrations/flask_api.py |
REST endpoints for all major resources |
from roboat import (
UserNotFoundError, GameNotFoundError,
RateLimitedError, NotAuthenticatedError, RoboatAPIError,
)
from roboat.utils import retry
@retry(max_attempts=3, backoff=2.0)
def safe_get(user_id):
return client.users.get_user(user_id)
try:
user = safe_get(99999999999)
except UserNotFoundError:
print("User not found")
except RateLimitedError:
print("Rate limited")
except NotAuthenticatedError:
print("Need OAuth token")
except RoboatAPIError as e:
print(f"API error: {e}")from roboat.utils import Paginator
# Lazily iterate ALL followers — auto-fetches every page
for follower in Paginator(
lambda cursor: client.friends.get_followers(156, limit=100, cursor=cursor)
):
print(follower)
# Collect first 500
top_500 = Paginator(
lambda c: client.friends.get_followers(156, limit=100, cursor=c),
max_items=500,
).collect()| Command | Description |
|---|---|
start <userid> |
Begin session (required first) |
auth |
OAuth login — browser opens, 120s |
whoami |
Current session info |
newdb / loaddb / listdb |
Database management |
user <id> |
User profile |
game <id> |
Game stats + votes |
friends / followers <id> |
Social counts |
likes <id> |
Vote breakdown |
search user/game <kw> |
Search |
presence / avatar <id> |
Status + avatar |
servers <placeid> |
Active servers |
badges <id> |
Game badges |
catalog <keyword> |
Shop search |
trades |
Trade list |
inventory / rap <id> |
Limiteds + RAP |
messages |
Private messages |
owns <uid> <assetid> |
Ownership check |
universe <id> |
Developer universe info |
save user/game <id> |
Save to DB |
cache [clear] |
Cache stats |
watch <id> |
Visit milestone alerts |
history / clear / exit |
Utility |
MIT License
Copyright (c) 2024 roboat contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Full license: LICENSE