Offsets

Windows · macOS · Android · home

Offsets are memory layout constants for one exact Roblox build. They are keyed by the build's identity, not its dotted version, because two builds can share a dotted version and offsets from the wrong one are worse than no offsets at all.

Three tiers

TierWhat it is
finalThe two below, composed — and what you get. Generated here; never uploaded, never mirrored.
verifiedDumped and checked by rbxoffsets, exactly as uploaded.
defaultA real dump produced by somebody else and mirrored here, exactly as mirrored.

Unless you ask otherwise you get the composed set when the build has one, and the better single input when it does not. Every response says which. Add ?tier=verified or ?tier=default to pin one input exactly. The rules in full are on Offset tiers.

Why a build is composed rather than chosen

Windows has two dumps per build and they are good at different things, so picking one means shipping a set that is missing something the other had:

  • Ours reads the client's own reflection database, so it finds far more — on 0.738 it has 1,083 offsets the mirrored dump has no entry for at all — and where both have a value ours is derived rather than pattern-matched.
  • But a reflected property is the only kind it can see. TaskScheduler, VisualEngine, Instance.This, Humanoid.Health and 258 others have no property descriptor anywhere in the client, so that mechanism will never reach them however good it gets. The mirrored dump has them.

So neither is served. Both are kept whole, and a third set is built from them:

#Rule
1Every offset either side names is in the result. Nothing is dropped.
2Where both have a usable value and they disagree, the mirrored value is served. Ours wins only where the mirrored dump has no value or a zero.
3A zero is not a usable value. A real value from either side beats a zero from the other, whoever it belongs to.
4Where only one side has an offset, that side's value is served.

Rule 3 is not hypothetical: the mirrored dump publishes 0x0 for about a dozen fields it failed to find, and the composed set replaces each one where we have a real answer.

Composing is not a judgement about who is right. Deciding between two disagreeing values needs a live client, and a build step is the wrong place to guess. The rule above is a stated precedence, and every offset records which side it came from — so the comparison shows you the decision rather than asking you to trust it.

Seeing what composition did

Every offset in a composed set records which dump it came from, and both routes below report it. Use them when you want to know not just whose dump you have but which parts of it are whose:

GET /api/v1/windows/offsets/{version}/diff              # every offset, with both values
GET /api/v1/windows/offsets/{version}/diff?from=disputed     # only the disagreements
fromMeaning
oursOnly the verified dump names it.
theirsOnly the mirrored dump names it — carried across.
agreedBoth name it and agree.
disputedBoth name it, they disagree, the mirrored value is served and ours is kept visible.
repairedThe mirrored dump published zero; ours has a real value.
filledOurs published zero; the mirrored value is served.
unknownNeither found it. Served as zero — do not trust these.

The same thing for a reader, laid out like a code review, is at /windows/offsets/{version}/diff. A build with fewer than two dumps answers 404 no_composition, which is the ordinary state before we publish rather than an error in the request.

Asking the question on its own

Every offsets response already carries tier, and every file redirect carries x-offsets-tier, so a client that reads either one already knows whose dump it got. When that is the question — a launcher deciding how much to trust a build, a dashboard showing a badge — there is a route that answers it and nothing else:

GET /api/v1/windows/verified/{version}        # JSON
GET /api/v1/windows/verified/{version}.txt    # the word "true" or "false", nothing else

verified: true means the set served for that build contains our work — either our dump on its own, or the composed set, which only exists when ours does. false means you are getting the mirrored dump alone. composed: true in the JSON tells the two apart, and links to the diff. latest works in place of a version and resolves to the same build /offsets/latest does.

A build with no offsets at all answers 404, not false. “We serve somebody else's dump for this build” and “there is nothing to serve for this build” are different facts, and a client that collapses them will report an unknown build as unverified. Treat 404 as “no answer yet”.

Where they come from

Platformverifieddefault
WindowsPublished by rbxoffsetsMirrored from theo's offsets
macOSPublished by rbxoffsetsNo upstream publishes one
AndroidPublished by rbxoffsetsNo upstream publishes one

Default dumps are copied rather than hotlinked, for three reasons in order of how much they matter: they stay reachable for builds upstream has aged out; an outage there does not take these pages down with it; and a stable URL under one domain is the thing an integration can actually depend on. Upstream is credited on every page and in every response that serves its work.

How rarely upstream is asked

Upstream is one person's server, so the mirror is built around restraint. It reads upstream's build listing — one request that names every build and every file — no more often than upstream's own cache lifetime (every 7 minutes), and conditionally, so an unchanged listing costs a 304 and no body. Each file is then fetched once, ever, unless the listing says upstream republished it. At most 24 files are fetched per cycle, newest builds first. The listing also names builds before they go live, which is how default offsets for upcoming builds are picked up.

What is in a dump

The four offsets formats are the same data written four ways — which is right depends on your toolchain, so none is recommended:

FormatWhat it is
hppA C++ header.
csThe same constants as a C# class.
jsonThe structured form, and the dump's own description: total count, when it was produced, which dumper made it, and which build it belongs to.
txtA flat table, for grepping.

A dump can also carry offsetshex.json, struct.hpp, types.json, fflags.hpp, fflags.json, fflags.cs, fflags.txt, fflagshex.json — see FFlags and dump files.

Fetching them

# builds with offsets, each in its served tier
curl -s https://rbxoffsets.com/api/v1/windows/offsets
curl -s "https://rbxoffsets.com/api/v1/windows/offsets?tier=verified"

# one build's set, and which tiers it has
curl -s https://rbxoffsets.com/api/v1/windows/offsets/version-c5aecda2245e4fae
curl -s https://rbxoffsets.com/api/v1/windows/offsets/latest

# the file itself (a redirect - use -L)
curl -sL -o offsets.hpp https://rbxoffsets.com/api/v1/windows/offsets/latest/hpp
curl -sL -o offsets.hpp "https://rbxoffsets.com/api/v1/windows/offsets/latest/hpp?tier=verified"
curl -sL -o offsets.hpp https://rbxoffsets.com/api/v1/windows/offsets/version-c5aecda2245e4fae/default/offsets.hpp

A version query answers like this:

{
  "platform": "windows",
  "version": "version-c5aecda2245e4fae",
  "displayVersion": "0.738.0.7381397",
  "tier": "verified",
  "availableTiers": ["verified", "default"],
  "count": 392,
  "dumpedAt": "2026-09-09T18:02:00.000Z",
  "storedAt": "2026-09-09T18:05:11.000Z",
  "source": "upload",
  "dumper": "rbxoffsets-dumper",
  "dumperVersion": "1.0.0",
  "verifiedBy": "jude",
  "verifiedAt": "2026-09-09T18:20:00.000Z",
  "notes": null,
  "credit": { "label": "rbxoffsets", "url": null },
  "isProduction": true,
  "isLatest": true,
  "files": [
    {
      "file": "offsets.hpp",
      "kind": "offsets",
      "format": "hpp",
      "sizeBytes": 25930,
      "sha256": "…",
      "path": "/api/v1/windows/offsets/version-c5aecda2245e4fae/verified/offsets.hpp",
      "url": "https://rbxoffsets.com/api/v1/windows/offsets/version-c5aecda2245e4fae/verified/offsets.hpp"
    }
  ]
}

Matching offsets to a running client

The reliable sequence, and the reason version is the identity:

  1. Read the client's own version. On Windows that is the clientVersionUpload from clientsettingscdn.roblox.com/v2/client-version/WindowsPlayer, or the Roblox Version string at the top of any dump.
  2. Ask this API for that exact string — with ?tier=verified if you require it.
  3. If it answers 404 offsets_not_found or 404 offsets_not_verified, the dump has not been published yet. Do not fall back to latest. Offsets from a neighbouring build are not approximately right; they point at the wrong memory.
version=$(curl -s https://clientsettingscdn.roblox.com/v2/client-version/WindowsPlayer \
          | jq -r .clientVersionUpload)
curl -fsSL -o offsets.hpp "https://rbxoffsets.com/api/v1/windows/offsets/$version/hpp?tier=verified" \
  || echo "no verified dump for $version yet"

macOS

No upstream publishes macOS dumps, so macOS has no default tier. Until the first verified set is uploaded, its offsets routes answer 501 offsets_unsupported — deliberately not a 404, because the route is correct and the capability is what is missing. The moment a verified set lands, they answer a real listing with no change on your side.

Publishing a dump

Operator work, token required, and it only ever creates the verified tier:

curl -X POST -H "Authorization: Bearer $HTTP_TOKEN" \
  -F offsets.json=@offsets.json -F offsets.hpp=@offsets.hpp \
  -F offsets.cs=@offsets.cs -F offsets.txt=@offsets.txt -F verified_by=you \
  https://rbxoffsets.com/internal/offsets/windows/version-c5aecda2245e4fae

What an upload has to satisfy

A verified set replaces the default one in everything served for that build, so an upload is checked before it can do that — and refused as a whole rather than half-applied, so a bad upload never costs the working set it was meant to supersede.

RuleWhy
offsets.json must name this build in Roblox Version, or name nothing at allA dump filed under the wrong build is the most damaging mistake this service could make.
It must carry a non-empty Offsets object of classesThat is the shape every client reads. A body that parses but is shaped differently breaks each build it lands on.
It must not drop any Class.Member the default set already servesCoverage cannot go backwards. A dump can be far larger overall and still be missing the keys clients actually read — this is the common case for a dumper built on a different technique — and publishing it would take a working build and break it.

The coverage refusal names the keys that went missing, so the answer is a list to go and add rather than a rejection to puzzle over. It applies only where a default set exists to compare with; a build nobody else has dumped has nothing to regress against. Set OFFSETS_REQUIRE_COVERAGE=false to publish anyway.

Every way in — PowerShell, cmd, the CLI, writing straight to the bucket — and how to withdraw a bad set, is on Publishing offsets.