⚡ Install
pip install roboat
pip install "roboat[async]"
pip install "roboat[all]"
🚀 Quick Start
from roboat import RoboatClient
client = RoboatClient()
user = client.users.get_user(156)
print(user)
game = client.games.get_game(2753915549)
print(f"{game.name} — {game.visits:,} visits | {game.playing:,} playing")
items = client.catalog.search(keyword="fedora", category="Accessories", sort_type="Sales")
for item in items:
print(f"{item.name} — {item.price}R$")
🖥️ Interactive Terminal
roboat
____ _ _ _ ____ ___
| _ \ ___ | |__ | | _____ __/ \ | _ \_ _|
| |_) / _ \| '_ \| |/ _ \ \/ / _ \ | |_) | |
| _ < (_) | |_) | | (_) > < ___ \| __/| |
|_| \_\___/|_.__/|_|\___/_/\_/_/ \_|_| |___|
roboat v2.1.0 — roboat.pro — type 'help' to begin
» start 156
» auth
» game 2753915549
» inventory 156
» rap 156
» likes 2753915549
» friends 156
🔐 OAuth Authentication
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()
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.
📦 Repository Structure
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
🧠 Clients
Sync — RoboatClient
from roboat import RoboatClient, ClientBuilder
client = RoboatClient()
client = (
ClientBuilder()
.set_oauth_token("TOKEN")
.set_timeout(15)
.set_cache_ttl(60)
.set_rate_limit(10)
.set_proxy("http://proxy:8080")
.build()
)
Async — AsyncRoboatClient
import asyncio
from roboat import AsyncRoboatClient
async def main():
async with AsyncRoboatClient() as client:
game, votes, icons = await asyncio.gather(
client.games.get_game(2753915549),
client.games.get_votes([2753915549]),
client.thumbnails.get_game_icons([2753915549]),
)
users = await client.users.get_users_by_ids(list(range(1, 501)))
print(f"Fetched {len(users)} users")
asyncio.run(main())
Open Cloud — RoboatCloudClient
from roboat import RoboatCloudClient
cloud = RoboatCloudClient(api_key="roblox-KEY-xxxxx")
cloud.datastores.set(universe_id, "PlayerData", "player_1", {"coins": 500})
📡 API Coverage
| 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 |
👤 Users
user = client.users.get_user(156)
users = client.users.get_users_by_ids([1, 156, 261])
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")
🎮 Games
game = client.games.get_game(2753915549)
game = client.games.get_game_from_place(6872265039)
visits = client.games.get_visits([2753915549, 286090429])
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)
👥 Groups
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)
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)
client.groups.pay_out(7, user_id=1234, amount=500)
💰 Marketplace & Economy
from roboat.marketplace import MarketplaceAPI
market = MarketplaceAPI(client)
data = market.get_limited_data(1365767)
print(f"{data.name} RAP: {data.recent_average_price:,}R$ Trend: {data.price_trend}")
profit = market.estimate_resale_profit(1365767, purchase_price=12000)
print(f"Net profit: {profit.estimated_profit:,}R$ ROI: {profit.roi_percent}%")
deals = market.find_underpriced_limiteds([1365767, 1028606, 19027209])
tracker = market.create_rap_tracker([1365767, 1028606])
tracker.snapshot()
tracker.snapshot()
print(tracker.summary())
🤝 Social Graph
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])
suggestions = sg.follow_suggestions(156, limit=10)
🔧 Open Cloud — Developer Tools
API_KEY = "roblox-KEY-xxxxx"
UNIVERSE = 123456789
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)
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)
client.develop.announce(UNIVERSE, API_KEY, "Double XP starts now!")
client.develop.broadcast_shutdown(UNIVERSE, API_KEY)
client.develop.ban_user(UNIVERSE, 1234, API_KEY, duration_seconds=86400,
display_reason="Temporarily banned.")
client.develop.unban_user(UNIVERSE, 1234, API_KEY)
🗄️ Database Layer
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())
db.close()
⚡ Events
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)
🛠️ CLI Tools
python tools/bulk_lookup.py --ids 1 156 261 --format csv
python tools/bulk_lookup.py --usernames Roblox builderman --format json
python tools/rap_snapshot.py --user 156
python tools/rap_snapshot.py --user 156 --diff
python tools/game_monitor.py --universe 2753915549 --interval 60
python scripts/check_env.py
python scripts/generate_stub.py
🔗 Integrations
| Discord Bot | integrations/discord_bot.py | Slash commands: /user, /game, /status |
| Flask REST API | integrations/flask_api.py | REST endpoints for all major resources |
🚨 Error Handling
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
for follower in Paginator(
lambda cursor: client.friends.get_followers(156, limit=100, cursor=cursor)
):
print(follower)
top_500 = Paginator(
lambda c: client.friends.get_followers(156, limit=100, cursor=c),
max_items=500,
).collect()
📋 Terminal Commands
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 |
⚖️ License
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