How GraphQL describes itself
Every GraphQL server ships a meta-schema that lets clients ask the API about its
own shape. This introspection system powers GraphiQL, schema documentation,
client code generation and validation. This reference lists the introspection
meta-types — __Schema, __Type, __Field, __InputValue, __EnumValue,
__Directive — their fields, the __TypeKind enum, and the three meta-fields
you can call directly inside any query.
How it works
You explore a schema by querying the __schema or __type root meta-fields.
Because types can be wrapped in lists and non-null markers, __Type is
recursive: wrapping kinds carry a null name and an ofType pointer:
{
__type(name: "User") {
name
kind
fields {
name
type { kind name ofType { kind name } }
}
}
}
To resolve a type like [String!]! you peel ofType one layer at a time:
NON_NULL → LIST → NON_NULL → SCALAR(String). Which __Type fields are
populated depends on kind: fields only appears on OBJECT/INTERFACE,
enumValues only on ENUM, inputFields only on INPUT_OBJECT.
The TypeKind enum in full
All eight possible __TypeKind values and what they mean:
| Kind | Meaning | Key fields populated |
|---|---|---|
| SCALAR | Leaf type (Int, String, Boolean, etc.) | name |
| OBJECT | Named type with fields | fields, interfaces |
| INTERFACE | Abstract type that objects can implement | fields, possibleTypes |
| UNION | Type that is one of several objects | possibleTypes |
| ENUM | Type with discrete named values | enumValues |
| INPUT_OBJECT | Input-only type (for arguments) | inputFields |
| LIST | Wrapping type for arrays | ofType |
| NON_NULL | Wrapping type for non-nullable | ofType |
The last two have no name — they are structural wrappers pointing to the inner type through ofType.
The three meta-fields you can use in any query
__typename— available on every object type; returns the concrete type name as a string. Essential for discriminating union and interface members on the client side. For example,... on Dog { __typename name }inside a pets union tells the client which animal was actually returned.__type(name: String!)— available on the root Query type; returns the__Typefor any named type in the schema. Use it to inspect a single type’s fields and kind at runtime.__schema— available on the root Query type; returns the full__Schemaobject, including thequeryType,mutationType,subscriptionType, all types, and all directives.
Practical use: code generation and tooling
The introspection system is what makes code generators like GraphQL Code Generator, Apollo Client’s type policies, and Relay’s compiler work. They run the full introspection query ({ __schema { types { name kind fields { ... } } } }) against a development server to learn the exact shape of every type, then emit TypeScript types, fragment matchers, or operation-specific interfaces automatically.
This is also why disabling introspection in production matters for security: a client that can query __schema can enumerate every type, field, and argument in your API — a useful feature in development and a surface for reconnaissance in production.
Notes and gotchas
The __typename meta-field is the workhorse for client-side union and interface
resolution — it returns the concrete object type. All introspection names use a
reserved double-underscore prefix that your own schema may never use. Finally,
remember that introspection is frequently disabled in production, so do not build
runtime features that depend on a live __schema query against a hardened API.