FriendPath API Documentation
Programmatic access to the same engine that powers friendpath.arbastro.com. Two public APIs: the Scan API resolves the connection path between two Roblox users; the Famous Users API returns a curated list of well-known Roblox accounts. The Scan API is metered (with a generous Suite-member free tier); the Famous Users API is completely free.
Introduction
FriendPath traces degrees of separation between any two Roblox players using bidirectional BFS through
Roblox's public friend graph. Maximum depth is 20. Most queries between active players resolve in 2–4
degrees and complete in under 5 seconds. Edge cases (very inactive accounts, banned users, hidden friend lists)
may take up to 30 seconds or return not_found.
Authentication
The Scan API authenticates via API keys passed as a Bearer token in the Authorization header.
API keys begin with ak_live_ and are tied to your arbastro account. Each key is shown to you exactly
once at creation; we only store its SHA-256 hash. You can revoke a key at any time from your settings.
The Famous Users API requires no authentication.
Step 1 — Create an arbastro account
FriendPath shares its account system with arbastro.com. If you don't already have an arbastro account, head to arbastro.com/signup and complete the 5-step signup (email + password, link Discord, link Roblox, pick username, recommendations). The whole thing takes about 3 minutes.
Step 2 — Generate an API key
- Sign in at arbastro.com/login
- Go to Settings → API keys
- Click Generate, give it a label (e.g. "my discord bot")
- Copy the key immediately — it's shown once. Lost keys must be regenerated.
- If you don't have arbastro Suite, click Add card first to enable metered billing
Step 3 (optional) — Get arbastro Suite for free daily quota
arbastro Suite is a $4.99/month (or $4.17/month yearly) subscription that includes 50 free FriendPath Scan API calls per day, ad-free FriendPath usage, priority support, and subsidiary-giveaway eligibility. New users get a 30-day free trial.
Without Suite, you can still use the API — you just pay per call from request #1. With Suite, the first 50 calls per day each UTC day are free; calls 51+ are billed at the same metered rate.
Scan API — Overview
Resolve any two Roblox usernames or numeric user IDs and receive their connection path through the friend graph.
Endpoint
https://arbastro.com/api/v1/friendpath/path
Parameters
| Param | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Roblox username or numeric ID. Numbers are treated as user IDs; non-numbers as usernames. |
to | string | Yes | Same as from — the other end of the path. |
maxDepth | number | No | Maximum BFS depth. Default 20. Lower values fail faster on disconnected pairs. |
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer ak_live_... — your API key |
Response shape
Returns a JSON object describing the path between the two users:
// 200 OK — path found
{
"from": { "input": "Builderman", "userId": 156 },
"to": { "input": "david.baszucki", "userId": 5208617297 },
"result": {
"type": "done",
"degrees": 2,
"visited": 14328,
"path": [
{ "id": 156, "username": "Builderman" },
{ "id": 119358574, "username": "someMutual" },
{ "id": 5208617297, "username": "david.baszucki" }
]
}
}
Code examples
Click a tab below to view the example for your language.
curl "https://arbastro.com/api/v1/friendpath/path?from=Builderman&to=david.baszucki" \
-H "Authorization: Bearer ak_live_YOUR_KEY"
// Browser or Node 18+ (uses fetch)
const res = await fetch(
"https://arbastro.com/api/v1/friendpath/path?from=Builderman&to=david.baszucki",
{ "headers": { "Authorization": "Bearer ak_live_YOUR_KEY" } }
);
const data = await res.json();
// data.result.degrees === 2
// data.result.path === [{id, username}, ...]
console.log(`degrees: ${data.result.degrees}`);
type PathResult = {
from: { input: string; userId: number };
to: { input: string; userId: number };
result: {
type: "done" | "not_found" | "error";
degrees?: number;
visited?: number;
path?: { id: number; username: string }[];
};
};
async function scanPath(from: string, to: string): Promise<PathResult> {
const u = new URL("https://arbastro.com/api/v1/friendpath/path");
u.searchParams.set("from", from);
u.searchParams.set("to", to);
const r = await fetch(u, {
headers: { Authorization: `Bearer ${process.env.FRIENDPATH_KEY}` }
});
if (!r.ok) throw new Error(`scan failed: ${r.status}`);
return r.json();
}
import os, requests
def scan_path(a: str, b: str) -> dict:
key = os.environ["FRIENDPATH_KEY"]
r = requests.get(
"https://arbastro.com/api/v1/friendpath/path",
params={"from": a, "to": b},
headers={"Authorization": f"Bearer {key}"},
timeout=60,
)
r.raise_for_status()
return r.json()
data = scan_path("Builderman", "david.baszucki")
print(f"degrees: {data['result']['degrees']}")
--!strict
-- ServerScript — drop in ServerScriptService
-- Game Settings → Security → Allow HTTP Requests must be ON
local HttpService = game:GetService("HttpService")
local FRIENDPATH_KEY: string = "ak_live_YOUR_KEY"
local API_BASE: string = "https://arbastro.com/api/v1/friendpath/path"
type PathNode = { Id: number, Username: string }
type ScanResult = {
Found: boolean,
Degrees: number?,
Path: { PathNode }?,
Error: string?,
}
local function ScanFriendPath(FromUser: string, ToUser: string): ScanResult
local Url = API_BASE
.. "?from=" .. HttpService:UrlEncode(FromUser)
.. "&to=" .. HttpService:UrlEncode(ToUser)
local Ok, Response = pcall(function()
return HttpService:RequestAsync({
Url = Url,
Method = "GET",
Headers = {
["Authorization"] = "Bearer " .. FRIENDPATH_KEY,
},
})
end)
if not Ok or not Response.Success then
return { Found = false, Error = "http error" } :: ScanResult
end
local Body = HttpService:JSONDecode(Response.Body)
local Result = Body.result
if Result.type ~= "done" then
return { Found = false, Error = Result.type } :: ScanResult
end
local Path: { PathNode } = {}
for _, Node in ipairs(Result.path) do
table.insert(Path, { Id = Node.id, Username = Node.username })
end
return {
Found = true,
Degrees = Result.degrees,
Path = Path,
} :: ScanResult
end
-- Usage:
local Result = ScanFriendPath("Builderman", "david.baszucki")
if Result.Found then
print("degrees:", Result.Degrees)
end
// discord.js v14 — slash command /friendpath
const { SlashCommandBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("friendpath")
.setDescription("degrees of separation between two Roblox users")
.addStringOption(o => o.setName("from").setRequired(true))
.addStringOption(o => o.setName("to").setRequired(true)),
async execute(i) {
await i.deferReply();
const u = new URL("https://arbastro.com/api/v1/friendpath/path");
u.searchParams.set("from", i.options.getString("from"));
u.searchParams.set("to", i.options.getString("to"));
const r = await fetch(u, {
headers: { Authorization: `Bearer ${process.env.FRIENDPATH_KEY}` }
});
const data = await r.json();
if (data.result?.type !== "done") return i.editReply("no path found 😕");
await i.editReply(
`**${data.result.degrees} degrees** apart\n` +
data.result.path.map(n => `• ${n.username}`).join("\n")
);
}
};
package friendpath
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
type PathResult struct {
Result struct {
Type string
Degrees int
Path []struct{ Id int64; Username string }
} `json:"result"`
}
func Scan(from, to string) (*PathResult, error) {
u, _ := url.Parse("https://arbastro.com/api/v1/friendpath/path")
q := u.Query()
q.Set("from", from); q.Set("to", to); u.RawQuery = q.Encode()
req, _ := http.NewRequest("GET", u.String(), nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("FRIENDPATH_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer resp.Body.Close()
out := &PathResult{}
return out, json.NewDecoder(resp.Body).Decode(out)
}
Live runner
Test the Scan API directly from this page. You'll need an API key — paste yours below or grab one.
Try the Scan API
Errors
| Status | Body error | Cause |
|---|---|---|
| 400 | from and to are required | Missing query param |
| 401 | missing or invalid api key / api key revoked | Bearer token bad |
| 402 | payment_method_required | Out of free quota and no card on file |
| 404 | — | Username didn't resolve to a user |
| 502 | upstream friendpath unreachable | Backend overloaded — retry |
Billing & rate limits
Each successful Scan API call costs $0.005. arbastro Suite members get 50 free calls per UTC day before metering kicks in. Quota resets at 00:00 UTC.
There are no per-second rate limits today, but please don't spam — we may add throttling if you start to abuse. For high-volume use cases (>10k calls/day), email contact@arbastro.com to discuss.
Famous Users API — Overview
Returns a curated list of "famous" Roblox users, including arbastro and subsidiary group members and creators from the Rolimons gamelist. Updated daily. Used internally by FriendPath's dice-roll button. Free for anyone, no API key, no signup.
Endpoint
https://friendpath.arbastro.com/api/famous-users
Response shape
Returns an array of user objects:
// 200 OK
[
{
"id": 156,
"name": "Builderman",
"displayName": "Builderman",
"followers": 5_182_341,
"friends": 96
},
{ "id": 5208617297, "name": "david.baszucki", ... },
...
]
The list contains roughly 200–500 entries depending on the day's gamelist data. Order is approximately by follower count, with the hardcoded "always-included" accounts first.
Code examples
curl "https://friendpath.arbastro.com/api/famous-users"
const famous = await fetch("https://friendpath.arbastro.com/api/famous-users")
.then(r => r.json());
// Pick a random one
const picked = famous[Math.floor(Math.random() * famous.length)];
console.log(`random famous: ${picked.name}`);
import requests, random
famous = requests.get("https://friendpath.arbastro.com/api/famous-users").json()
picked = random.choice(famous)
print(f"random famous: {picked['name']}")
--!strict
local HttpService = game:GetService("HttpService")
type FamousUser = {
Id: number,
Name: string,
DisplayName: string?,
Followers: number?,
Friends: number?,
}
local function FetchFamousUsers(): { FamousUser }
local RawJson: string = HttpService:GetAsync(
"https://friendpath.arbastro.com/api/famous-users"
)
local Decoded = HttpService:JSONDecode(RawJson)
local List: { FamousUser } = {}
for _, U in ipairs(Decoded) do
table.insert(List, {
Id = U.id,
Name = U.name,
DisplayName = U.displayName,
Followers = U.followers,
Friends = U.friends,
})
end
return List
end
-- Usage:
local Famous = FetchFamousUsers()
local Picked = Famous[math.random(#Famous)]
print("random famous:", Picked.Name)
Live runner
Hit "Fetch" — no key needed.
Try the Famous Users API
How the list is built & fair use
The list is assembled at server boot from three sources, deduplicated, and refreshed daily:
- Hardcoded famous accounts — David Baszucki, Builderman, Shedletsky, KreekCraft, etc. — a small curated seed list.
- Roblox group creators — the owners of every game returned by
https://api.rolimons.com/games/v1/gamelist. When a game is owned by a Roblox group, the group's owner user is added. - "Top Playing Now" creators — fetched once per day from
https://apis.roblox.com/explore-api/v1/get-sort-content?sortId=top-playing-now. - Roblox staff & Star Creators — every member of the Official Roblox group (1200769, Roblox employees) and the Roblox Star Creators group (4199740) is included.
The endpoint serves a cached list — please don't poll faster than once per 5 minutes. Heavy abuse may result in IP-level rate limiting. No authentication required for normal usage.
Type definitions reference
TypeScript
export type FriendPathScanResult = {
from: { input: string; userId: number };
to: { input: string; userId: number };
result: {
type: "done" | "not_found" | "error";
degrees?: number;
visited?: number;
path?: FriendPathNode[];
message?: string;
};
};
export type FriendPathNode = {
id: number;
username: string;
};
export type FamousUser = {
id: number;
name: string;
displayName: string;
followers?: number;
friends?: number;
};
Changelog
- 2026-05 — Public docs page launched.
- 2026-05 — Famous Users API made publicly callable (no key).
- 2026-05 — Scan API moved behind arbastro accounts + metered billing.
Get help
Stuck? Three ways to reach us:
- Email contact@arbastro.com
- Open a ticket in the arbastro Discord #support channel
- Use the contact form at arbastro.com/#contact