Cloud Parts

GraphQL-core

The Python port of GraphQL.js: the parser, validator and executor that Strawberry, Ariadne and Graphene all run on.

What it is
API frameworks (graphql libraries)
Type
Open source
Made by
GraphQL-Python community (created and maintained by Christoph Zwerschke)
License
MIT
Facts checked
9 October 2026

What it is

GraphQL-core is a Python port of GraphQL.js, the reference implementation of GraphQL, and it copies that code as closely as Python allows, down to a test suite of more than 3,000 unit tests that mirrors the JavaScript one. It does two things: it builds a type schema, and it runs requests against that schema. You build a schema from objects such as GraphQLObjectType and GraphQLField, and give fields a resolve function. A resolver gets the parent value and a GraphQLResolveInfo object, whose context holds per-request state such as the logged-in user or a database session. Field arguments arrive as keyword arguments, where GraphQL.js passes them as one object. graphql_sync() parses the document, validates it against the schema and only then executes it. graphql() does the same for resolvers that are coroutines, using asyncio. There’s no HTTP layer, so most people never call it directly: Graphene, Ariadne and Strawberry build their schemas with it and run every query through its executor.

The version numbers follow GraphQL.js, not SemVer: a new major version of GraphQL.js becomes a new minor version of GraphQL-core, and that minor version can break the API. Version 3.3.0 (September 27, 2026) follows GraphQL.js 17.0.2 and supports Python 3.10 to 3.15. It adds incremental delivery with @defer and @stream (experimental, following the current spec proposal), cancellation with an AbortSignal, and immutable AST nodes. The 3.2 line (3.2.13) still follows GraphQL.js 16 for projects that need Python 3.7 to 3.9. The maintainers recommend pinning with ~= 3.3.0.

Why teams pick it

  • Tracks the reference implementation closely and ports its tests, so parsing, validation and execution behave like GraphQL.js
  • One engine under the main Python libraries: Strawberry, Ariadne and Graphene all build on it, so spec fixes reach all of them
  • Type hints throughout, checked with mypy, and resolvers can be plain functions or asyncio coroutines
  • Keeps up with the spec: 3.3 brings GraphQL.js 17 features such as @defer and @stream to Python

Watch out for

  • Low level: schemas are built from verbose GraphQLField and GraphQLArgument objects, and there’s no server, so applications usually use a library on top
  • Not SemVer: a minor release can break the API, so dependents pin a patch range such as ~= 3.3.0
  • Asynchronous execution only through asyncio; GraphQL-core 2’s other executors are gone
  • Incremental delivery (@defer, @stream) and fragment arguments are experimental and follow spec proposals that may still change

The GraphQL-core family

3 technologies built from or on GraphQL-core

How it fits with other technologies

A schema with one query, run through parse, validate and execute · python

# pip install graphql-core   (3.3.0, Python 3.10+)
from graphql import (
    GraphQLField, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, GraphQLString,
    execute, parse, validate,
)

BOOKS = {"1": {"title": "Dune", "author": "Frank Herbert"}}

book_type = GraphQLObjectType("Book", {
    "title": GraphQLField(GraphQLNonNull(GraphQLString)),   # default resolver reads book["title"]
    "author": GraphQLField(GraphQLNonNull(GraphQLString)),
})

schema = GraphQLSchema(query=GraphQLObjectType("Query", {
    "book": GraphQLField(book_type, resolve=lambda root, info: BOOKS["1"]),
}))

# graphql_sync() runs these three steps; here they are one at a time
document = parse("{ book { title author } }")
print(validate(schema, document))   # []
print(execute(schema, document))
# ExecutionResult(data={'book': {'title': 'Dune', 'author': 'Frank Herbert'}}, errors=None)

print(validate(schema, parse("{ book { isbn } }"))[0].message)
# Cannot query field 'isbn' on type 'Book'.

See it in a real stack

GraphQL API in Python →
Live model
What you’re watchingClients post GraphQL queries (blue) to one endpoint. Uvicorn hands each request to FastAPI over ASGI, FastAPI routes it to Strawberry’s router, and graphql-core validates and executes it; resolvers load rows through SQLAlchemy from PostgreSQL, and the answer travels back the same way. Pink queries fail validation, so graphql-core answers them with an error list and the database never sees them. Green requests are plain REST calls that FastAPI validates with Pydantic models.
Where it came from2015–2026

Facebook published GraphQL.js in July 2015, and Python got its own port within months. Syrus Akbary released the first graphql-core package in October 2015: a port of GraphQL.js that also ran on Python 2.7, and the engine under Graphene, which Akbary also created. That port, now called GraphQL-core 2, stayed at the level of GraphQL.js 0.6.0.

In 2018 Christoph Zwerschke released GraphQL-core-next, a re-implementation for modern Python 3 that followed the then-current GraphQL.js 14 closely, added type hints and replicated its test suite. Its first public release, 1.0.0, came out in September 2018. Ariadne moved onto it in January 2019 because it supported async resolvers and a newer version of the spec. In November 2019 it was released as GraphQL-core 3.0.0, the successor to both GraphQL-core 2 and GraphQL-core-next.

Since then each GraphQL.js major version has become a GraphQL-core minor version: 3.1 followed GraphQL.js 15 in April 2020, 3.2 followed GraphQL.js 16 in January 2022, and 3.3 followed GraphQL.js 17 in September 2026, after a long run of alpha releases from 2022 on. Graphene 3, Ariadne and Strawberry all build on it.

Why it’s built this way

Port the reference implementation, tests included
The goal was to stay very close to GraphQL.js while offering a Pythonic API. Replicating its whole test suite with pytest keeps behavior compatible and makes each new GraphQL.js release straightforward to port.
Minor versions follow GraphQL.js major versions
A breaking release of GraphQL.js usually forces breaking changes in the port. Mapping it to a minor version keeps the major version at 3, and only patch releases promise full backward compatibility.
Type hints everywhere
GraphQL.js was typed with Flow and later TypeScript. The port uses Python type hints the same way, checked with mypy, which also helps the libraries built on top of it.
Drop legacy Python and custom executors
GraphQL-core 2 supported old Python versions and several executors. The rewrite aimed to be simple and cruft-free for current Python, so it supports asynchronous execution only through asyncio.

Timeline

  1. 2015

    First graphql-core release by Syrus Akbary, in October

  2. 2018

    GraphQL-core-next 1.0.0, based on GraphQL.js 14, in September

  3. 2019

    GraphQL-core 3.0.0 replaces GraphQL-core 2 and GraphQL-core-next in November

  4. 2020

    3.1.0 follows GraphQL.js 15 in April

  5. 2022

    3.2.0 follows GraphQL.js 16 in January

  6. 2026

    3.3.0 follows GraphQL.js 17 on September 27

Sources6 · facts checked 9 October 2026

Improve this page on GitHub