GraphQL Formatter: Beautify and Minify Queries, Mutations and Schemas
Free GraphQL formatter — beautify or minify queries, mutations, fragments and SDL schemas with a real parser. Syntax errors located by line and column.
Try it now: GraphQL Formatter — Format or minify a GraphQL query, mutation, fragment or SDL schema with a real parser — syntax errors show the exact line and column, nothing invented.
Why GraphQL Queries Get Unreadable Fast
A REST URL is flat — the path and query string are the whole request. A GraphQL query has no such ceiling: selection sets nest inside selection sets, fragments get spread into other fragments, and directives like @include and @skipattach conditions to individual fields. Add variable definitions at the top of the operation and it's easy to end up with a document five or six levels deep before you've queried anything unusual. None of that depth is a problem for the GraphQL engine executing it — it's a problem for the person reading it, especially once the query has been copy-pasted between a client codebase, a GraphiQL tab, and a bug report, each pass losing a little more of its original indentation.
A GraphQL formatter — sometimes searched for as a GraphQL beautifier or GraphQL prettify tool — exists for exactly that reason: it re-indents the document consistently based on its actual nesting, the same service a JSON formatter provides for deeply nested JSON. The underlying principle is identical in both cases — the formatter has to understand the document's structure, not just react to brace and bracket characters in the text.
Four Documents, One Grammar
“GraphQL” isn't one kind of document — a formatter that only handles queries is missing most of what people actually paste in. There are four related but distinct forms, all valid GraphQL syntax that a formatter needs to parse and print correctly:
- Queries — read operations, the most common case: a named operation with a selection set and, usually, variable definitions.
- Mutations — write operations. Structurally identical to a query (variables, a selection set, an operation name) but declared with the
mutationkeyword instead ofquery. - Fragments — a named, reusable selection set declared with
fragmentand spread into an operation with...FragmentName. Formatting a document that spreads three or four fragments into a query is where indentation drift shows up fastest, because each fragment was likely pasted in from a different file. - SDL — Schema Definition Language. This is the odd one out and worth being precise about: SDL is the syntax used to describe a schema —
type,input,enum,interface, andscalardeclarations — not to query one. A.graphqlschema file and a query sent from a client share a grammar family but serve opposite purposes: one defines what's queryable, the other queries it. A formatter that only recognizes operations will choke the moment you paste in a schema file, so it needs to parse both grammars.
Formatting a Query That Lost Its Indentation
The most common input in practice isn't hand-typed — it's a query copied out of a Slack thread, a network tab, or a minified bundle, where every newline collapsed into one line somewhere along the way. Reformatting it should recover exactly the structure the query already has, nothing added or reordered:
query GetUser($id: ID!, $includeOrders: Boolean = false) { user(id: $id) { id name email orders @include(if: $includeOrders) { id total items { sku quantity } } } }query GetUser($id: ID!, $includeOrders: Boolean = false) {
user(id: $id) {
id
name
email
orders @include(if: $includeOrders) {
id
total
items {
sku
quantity
}
}
}
}Notice the @include directive stays attached to the field it modifies rather than being pushed to its own line — a formatter that understands the grammar knows a directive is part of the field it decorates, not a standalone token to wrap independently.
A Real Parser Catches Syntax Errors; a Regex Just Hides Them
This is the detail worth being precise about, because it's the difference between a formatter you can trust and one that quietly lies to you. A GraphQL formatter built on a real parser — the same class of tool the reference GraphQL implementations use to validate a document before execution — has to build an actual syntax tree from the input. An unclosed brace, a variable definition missing its type, a dangling comma where the grammar doesn't allow one: all of these fail to parse, and a parser-based tool reports exactly where, with a line and column, the same way a real JSON parser reports a trailing comma.
A string-based reformatter — one that just counts braces and inserts indentation based on nesting depth inferred from characters — has no such check. Feed it a query with a brace missing and it will still produce something that looks tidy: consistent indentation, aligned fields, no visible complaint. It is still invalid GraphQL. It will fail the moment a client or server actually tries to parse it, just later and with a less useful error than the formatter could have given you up front.
query GetUser($id: ID!) {
user(id: $id) {
id
name
→ Syntax Error: Expected Name, found <EOF> (line 6, column 1)The missing closing brace for both user and the operation itself is a genuine syntax error, and a parser-backed formatter surfaces it instead of guessing at how to indent something that never had valid structure to begin with.
Format vs. Minify: Same Operation, Reversed
Format and minify a GraphQL query are the same transformation run in opposite directions — exactly the relationship between beautifying and minifying JSON. Format a query when a human is going to read it: a teammate reviewing a pull request, you debugging a resolver, or a query sitting in a .graphql file in a codebase where readability matters for the next person who touches it. Minify — strip whitespace, comments, and unnecessary line breaks — when only the bytes matter: a query embedded in a client bundle, sent over the wire, or persisted as an operation string on a server that supports persisted queries.
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
↓
query GetUser($id: ID!) { user(id: $id) { id name } }Neither direction changes what the query does. A client sending the minified form and a developer reading the formatted form in an IDE are looking at the same operation — the same guarantee a JSON minifier gives for data, applied here to an executable document instead.
Using the GraphQL Formatter
GenKitLab's GraphQL Formatter formats or minifies a query, mutation, fragment, or SDL schema document using a real GraphQL parser, so a genuine syntax error — an unclosed brace, a malformed variable definition — is reported with the exact line and column it occurs at, rather than papered over with indentation that merely looks correct. It runs entirely client-side: nothing you paste is uploaded anywhere, which matters for a query that includes field names or fragment structure you'd rather not send to a third-party server just to reformat it.
Frequently asked questions
›What does a GraphQL formatter actually do?
It parses a GraphQL document — a query, mutation, fragment, or SDL schema — into its actual structure and re-prints it with consistent indentation based on real nesting depth, rather than reacting to brace characters in the text. The operation itself is unchanged; only whitespace and layout differ.
›Can a GraphQL formatter handle schema files (SDL), not just queries?
It should. SDL — Schema Definition Language — is the syntax used to define a schema's types, inputs, enums, and interfaces, and it's a different grammar surface from an operation. A formatter that only parses queries and mutations will fail on a .graphql schema file, so a general-purpose one needs to support both.
›What's the difference between formatting and minifying a GraphQL query?
They're the same transformation in opposite directions. Formatting adds consistent indentation and line breaks for a human to read — reviewing a PR, debugging in an IDE. Minifying strips whitespace and comments down to the minimum needed to parse, which matters when the query is embedded in a client bundle or sent over the wire.
›Will a formatter fix a broken GraphQL query?
No — and a good one shouldn't try. A formatter built on a real parser reports a genuine syntax error, such as an unclosed brace or a malformed variable definition, with a line and column, the same way a JSON parser reports invalid JSON. A string-based reformatter that skips parsing will instead produce tidy-looking output for input that's still invalid GraphQL underneath.
›Do directives like @include and @skip affect formatting?
They stay attached to the field or fragment spread they modify rather than being placed on their own line — a directive is part of the element it decorates, not a standalone token, and a parser-based formatter reflects that in how it prints the document.
›Is it safe to format a query that contains sensitive field or variable names?
Yes, as long as the formatter runs client-side. GenKitLab's GraphQL Formatter processes the document entirely in your browser — nothing pasted into it is uploaded to a server, which matters for internal schemas or queries you don't want leaving your machine just to reformat them.
Last updated