# Source 2 Schema Explorer Browsable UI for the engine schemas (classes, enums, fields, metadata) of Source 2 games. Every class and enum has a prerendered HTML page, but crawling them is slow and the pages contain no more data than the JSON below. Do not crawl the site. There is no search or JSON API. For any lookup, download the raw schema for the game and search it with a script (jq, node, ...). Only these games are available: - Counter-Strike 2: https://s2v.app/SchemaExplorer/assets/cs2.json-pmbIpS8B.gz (0.8 MB gzipped / 8.3 MB raw, revision 10924896, Aug 19 2026) - Dota 2: https://s2v.app/SchemaExplorer/assets/dota2.json-xVjHUOgV.gz (1.4 MB gzipped / 13.2 MB raw, revision 10933339, Aug 22 2026) - Deadlock: https://s2v.app/SchemaExplorer/assets/deadlock.json-BkLvXOHB.gz (2.1 MB gzipped / 27.9 MB raw, revision 10912166, Aug 14 2026) URLs are content-hashed and change with each schema update; fetch https://s2v.app/SchemaExplorer/llms.txt to get the current ones. Files are plain gzip of a single JSON document. Parse with a script, never paste the file into context. Offsets and sizes are the runtime in-memory layout on Windows, not the on-disk resource layout. ## JSON structure ``` { generator, revision, version_date, version_time, classes: Class[], enums: Enum[] } Class { module, name, size, parents?: {module,name}[], fields?: Field[], metadata?: Meta[] } // size in bytes; parents = direct base classes only; fields = own only, not inherited Field { name, offset, type: Type, metadata?: Meta[] } // offset in bytes from class start Enum { module, name, alignment, members?: {name, value, metadata?: Meta[]}[], metadata?: Meta[] } // alignment = underlying C type as a string, e.g. "uint8_t"; value is a number Meta { name, value?: string } // value is raw unparsed text (string literals keep their quotes); absent for flag-only entries like MNotSaved. // Common: MPropertyFriendlyName, MPropertyDescription, MGetKV3ClassDefaults (class defaults as KV3-ish JSON text). // Networking metadata (MNetworkEnable, MNetworkVarNames, ...) is present only in Deadlock. Type { category, ...fields by category } builtin {name} | declared_class {module,name} | declared_enum {module,name} | ptr {inner: Type} fixed_array {inner: Type, count} | atomic {name, inner?: Type, inner2?: Type} | bitfield {count} // atomic = template container, e.g. CUtlVector, CUtlMap, CHandle // bitfield = count bits; bit position is not encoded (offset is always 0) ``` Declarations are keyed by (module, name). Besides "client" and "server" there are ~40 engine modules (entity2, animationsystem, particles, ...). The same name can exist in several modules (client/server variants of an entity), and a type reference may point to another module than the class using it (server classes commonly reference enums declared in "client") — do not filter type refs by module. ## Examples (jq; the node one-liner at the end works without jq) ``` # A class with all its fields gunzip -c cs2.json-pmbIpS8B.gz | jq '.classes[] | select(.module=="server" and .name=="CBaseEntity")' # Which classes declare a field named m_iHealth (own fields only — check parents for inherited) gunzip -c cs2.json-pmbIpS8B.gz | jq -r '.classes[] | select(any(.fields[]?; .name=="m_iHealth")) | .module + "/" + .name' # Fields whose type contains enum MoveType_t anywhere (inside ptr/array/template too) gunzip -c cs2.json-pmbIpS8B.gz | jq -r '.classes[] | (.module + "/" + .name) as $c | .fields[]? | select(any(.type | ..; objects and .category=="declared_enum" and .name=="MoveType_t")) | $c + "." + .name' # Enum members gunzip -c cs2.json-pmbIpS8B.gz | jq '.enums[] | select(.name=="MoveType_t").members[] | {name, value}' # Class not found? It may be renamed or in another module: search names by substring across all modules gunzip -c cs2.json-pmbIpS8B.gz | jq -r '.classes[] | select(.name | test("CreateWithinSphere")) | .module + "/" + .name' # All classes of one module (module list: [.classes[].module] | unique) gunzip -c cs2.json-pmbIpS8B.gz | jq -c '.classes[] | select(.module=="navlib") | {name, fields: [.fields[]?.name]}' # Without jq node -e 'const d=JSON.parse(require("zlib").gunzipSync(require("fs").readFileSync("cs2.json-pmbIpS8B.gz")));console.log(d.enums.find(e=>e.name=="MoveType_t").members)' ``` Site source: https://github.com/ValveResourceFormat/SchemaExplorer