Live game data,
right inside Arche.
Alchemy Connect lets a Roblox executor push a player's profile, live stats, inventory items, and images to Arche over a local WebSocket. Arche renders them in a modern, live-updating view that mirrors the in-game state without any polling.
Arche listens on ws://127.0.0.1:8765. Everything stays on your machine — no cloud upload, no third-party relay. Do not expose the port to the internet.
Quick start
Open Arche, switch to the Connect tab, and start a client that pushes JSON to the local socket. Send a profile first so Arche knows which Roblox user each subsequent update belongs to.
ws://127.0.0.1:8765 from your executor or a local script.profile.userId, profile.username, and optionally profile.displayName.stats, summary, items, and images in further messages.Connection
Arche hosts a single WebSocket server bound to loopback on port 8765. Multiple clients can connect at once — each connection is identified by the profile.userId it sends.
ws://127.0.0.1:8765
Lifecycle
Every message is a JSON object. On connect, send a profile message first. Arche keeps a client entry keyed by profile.userId and merges subsequent fields onto it.
If a client disconnects, Arche removes it from the list. Reconnect with the same userId to restore the view.
Message format
A message can include any combination of the fields below. The first message must contain profile.userId.
{
"profile": {
"userId": "12345678",
"username": "Player",
"displayName": "Player"
},
"game": "Blox Fruits",
"stats": [
{ "label": "Level", "value": "2450" },
{ "label": "Bounty", "value": "30.2M" }
],
"summary": [
{ "label": "Race", "value": "Angel" },
{ "label": "Fruit", "value": "Dough" }
],
"items": [
{ "name": "Dark Blade", "group": "Swords", "detail": "Mastery 600", "count": 1 }
],
"images": [
"https://example.com/screenshot.png"
]
}
| Field | Type | Description |
|---|---|---|
profile | object | Identifies the client. Required on the first message. Fields: userId, username, displayName. |
game | string | Optional game name shown under the profile. |
stats | array | Array of { label, value } stat tiles shown at the top. |
summary | array | Array of { label, value } summary cards. |
items | array | Array of inventory entries. Each can include name, group, detail, count, icon. |
images | array | Array of URLs or { url, caption } objects. |
Profile
The profile is used as the identity key for a client. Arche looks up profile.userId and groups all future messages under it.
{
"profile": {
"userId": "12345678",
"username": "RobloxPlayer123",
"displayName": "RobloxPlayer"
}
}
Avatar
Arche fetches a headshot automatically from Roblox thumbnails using the userId. If the fetch fails, the profile's first letter is shown instead.
Stats & summary
stats renders as a grid of large tiles at the top of the client view. summary renders below it as smaller cards. Both share the same { label, value } shape.
"stats": [
{ "label": "Level", "value": "2450" },
{ "label": "Playtime", "value": "48h 22m" }
],
"summary": [
{ "label": "Race", "value": "Angel" },
{ "label": "Fruit", "value": "Dough" }
]
Items
Items are the richest part of the data model. Each entry renders as a card grouped by the group field.
| Field | Type | Description |
|---|---|---|
name | string | Display name of the item. |
group | string | Section header (e.g. "Swords", "Fruits", "Materials"). |
detail | string | Subtitle (e.g. "Mastery 600", "Equipped"). |
count | number | Shows as ×N when greater than 1. |
icon | string | number | Roblox asset ID — see the accepted formats below. |
"items": [
{ "name": "Dark Blade", "group": "Swords", "detail": "Mastery 600" },
{ "name": "Dough", "group": "Fruits", "count": 2 },
{ "name": "God's Chalice", "group": "Materials", "count": 3 }
]
Asset ID formats
The icon field accepts any of the following — Arche extracts the numeric ID before requesting the thumbnail.
| Input | Result |
|---|---|
1234567890 (number) | OK |
"1234567890" | OK |
"rbxassetid://1234567890" | OK |
"rbxthumb://type=Asset&id=1234567890&w=150&h=150" | OK — the id query param is preferred. |
"rbxasset://textures/foo.png" | Not supported — local built-in assets cannot be fetched. |
Weapon mastery
For weapons, put the mastery in detail (e.g. "Mastery 600"). Arche renders it as a subtitle instead of a count badge.
Images
Arche renders images as clickable cards that open the full image in a new tab. Use direct HTTPS URLs that return an image file. Hosted JPEG/PNG/WebP are supported.
"images": [
"https://example.com/screenshot.png",
{
"url": "https://example.com/item.png",
"caption": "Rare item"
}
]
Example scripts
Lua (Roblox Executor)
local WS = WebSocket.connect("ws://127.0.0.1:8765")
local HttpService = game:GetService("HttpService")
local function send(payload)
WS:Send(HttpService:JSONEncode(payload))
end
local player = game.Players.LocalPlayer
send({
profile = {
userId = tostring(player.UserId),
username = player.Name,
displayName = player.DisplayName
},
game = "Blox Fruits"
})
while task.wait(5) do
send({
profile = { userId = tostring(player.UserId) },
stats = {
{ label = "Level", value = tostring(player.leaderstats.Level.Value) }
}
})
end
Lua — extract rbxassetid from tool textures
local function getAssetId(src)
if type(src) == "number" then return tostring(math.floor(src)) end
if type(src) ~= "string" then return nil end
local q = src:match("[&?]id=(%d+)")
if q then return q end
return src:match("(%d+)")
end
local items = {}
for _, tool in ipairs(player.Backpack:GetChildren()) do
if tool:IsA("Tool") then
table.insert(items, {
name = tool.Name,
group = "Inventory",
icon = getAssetId(tool.TextureId),
count = 1
})
end
end
Node.js
const WebSocket = require("ws");
const ws = new WebSocket("ws://127.0.0.1:8765");
ws.on("open", () => {
ws.send(JSON.stringify({
profile: { userId: "12345678", username: "Player", displayName: "Player" },
game: "Blox Fruits"
}));
ws.send(JSON.stringify({
profile: { userId: "12345678" },
stats: [{ label: "Level", value: "2450" }],
items: [{ name: "Dark Blade", group: "Swords", detail: "Mastery 600" }]
}));
});
Python
import asyncio, json
import websockets
async def main():
async with websockets.connect("ws://127.0.0.1:8765") as ws:
await ws.send(json.dumps({
"profile": {"userId": "12345678", "username": "Player"},
"game": "Blox Fruits"
}))
await ws.send(json.dumps({
"profile": {"userId": "12345678"},
"stats": [{"label": "Level", "value": "2450"}]
}))
await asyncio.sleep(60)
asyncio.run(main())
Troubleshooting
| Problem | Check |
|---|---|
| No client appears | Confirm Arche is running and the WebSocket URL uses port 8765. Ensure the first message contains profile.userId. |
| Profile appears but no stats | Send stats, summary, items, or images in a follow-up message. |
| Image card missing | Open the URL in a browser first. It must return an image over HTTPS with a permissive CORS/CORP header. |
| Connection refused | Restart Arche. If another process is holding port 8765, close it or change the port in the app settings. |
| Item icon not loading | Check the asset ID — Arche requests the Roblox thumbnail API. Private or moderated assets return a placeholder. |
| Duplicate clients | Two connections sending the same userId overwrite each other's data — use a unique identifier per executor. |
Alchemy