gql: GraphQL Client for Python

raw JSON →
4.0.0 verified Tue May 12 auth: no python install: verified

gql is a powerful and flexible GraphQL client library for Python, designed to simplify interacting with GraphQL APIs. It supports both synchronous and asynchronous operations, offering various transports like HTTP (via aiohttp, httpx, requests) and WebSockets. The library plays well with `graphql-core` and other GraphQL implementations, enabling features like local schema validation and dynamic query composition using a DSL module. The current stable version is 4.0.0, with active development including beta releases (e.g., v4.3.0b0) leading to future minor or major updates.

pip install "gql[all]"
breaking As of v4.0.0, the `gql()` and `dsl_gql()` functions now return a `GraphQLRequest` object instead of a `DocumentNode`. All `client.execute()` and `client.subscribe()` methods also now accept a `GraphQLRequest` object as their primary argument.
fix Update calls to `gql()` and `dsl_gql()` to expect `GraphQLRequest` objects. Pass `GraphQLRequest` objects directly to `execute()` and `subscribe()` methods. The `GraphQLRequest` object encapsulates the document, variable values, and operation name.
breaking The `AIOHTTPTransport`'s `ssl` parameter now defaults to `True` (enabling SSL certificate verification) starting from v4.0.0 (introduced in v4.0.0a0). Previously, it defaulted to `False` which could lead to security vulnerabilities by accepting self-signed certificates without warning.
fix If your GraphQL endpoint uses a self-signed or otherwise untrusted SSL certificate and you need to bypass verification (not recommended for production), explicitly set `ssl=False` in the `AIOHTTPTransport` constructor. Otherwise, ensure your certificates are properly configured and trusted.
breaking The `ConnectionClosed` exception has been replaced by `TransportConnectionClosed` for connection-related errors.
fix Update any exception handling blocks to catch `TransportConnectionClosed` instead of `ConnectionClosed`. Import the new exception from `gql.transport.exceptions`.
gotcha When using synchronous `client.execute()` or `client.subscribe()` methods from an asynchronous transport (like `AIOHTTPTransport`) in environments where an asyncio event loop is already running (e.g., Jupyter notebooks, IPython), it might cause issues or block. `gql` will try to run an event loop itself, which conflicts with an already running one.
fix In such environments, explicitly use the asynchronous `await session.execute(query)` pattern within an `async def` function. If you must use synchronous client methods, consider using libraries like `nest_asyncio` to patch the event loop for compatibility.
pip install gql
python os / libc variant status wheel install import disk
3.10 alpine (musl) all wheel - 0.31s 67.1M
3.10 alpine (musl) all - - 0.33s 67.2M
3.10 alpine (musl) gql wheel - 0.31s 24.4M
3.10 alpine (musl) gql - - 0.33s 24.7M
3.10 slim (glibc) all wheel 7.9s 0.21s 69M
3.10 slim (glibc) all - - 0.22s 70M
3.10 slim (glibc) gql wheel 3.3s 0.21s 25M
3.10 slim (glibc) gql - - 0.21s 26M
3.11 alpine (musl) all wheel - 0.49s 72.0M
3.11 alpine (musl) all - - 0.60s 72.1M
3.11 alpine (musl) gql wheel - 0.46s 26.8M
3.11 alpine (musl) gql - - 0.51s 27.2M
3.11 slim (glibc) all wheel 6.8s 0.42s 74M
3.11 slim (glibc) all - - 0.39s 75M
3.11 slim (glibc) gql wheel 2.9s 0.41s 28M
3.11 slim (glibc) gql - - 0.38s 28M
3.12 alpine (musl) all wheel - 0.66s 63.2M
3.12 alpine (musl) all - - 0.65s 63.4M
3.12 alpine (musl) gql wheel - 0.62s 18.6M
3.12 alpine (musl) gql - - 0.65s 19.0M
3.12 slim (glibc) all wheel 5.4s 0.57s 66M
3.12 slim (glibc) all - - 0.59s 66M
3.12 slim (glibc) gql wheel 2.5s 0.58s 19M
3.12 slim (glibc) gql - - 0.62s 20M
3.13 alpine (musl) all wheel - 0.66s 62.6M
3.13 alpine (musl) all - - 0.63s 62.7M
3.13 alpine (musl) gql wheel - 0.60s 18.0M
3.13 alpine (musl) gql - - 0.62s 18.2M
3.13 slim (glibc) all wheel 5.5s 0.58s 65M
3.13 slim (glibc) all - - 0.58s 65M
3.13 slim (glibc) gql wheel 2.5s 0.54s 19M
3.13 slim (glibc) gql - - 0.60s 19M
3.9 alpine (musl) all wheel - 0.28s 67.1M
3.9 alpine (musl) all - - 0.31s 67.1M
3.9 alpine (musl) gql wheel - 0.28s 24.6M
3.9 alpine (musl) gql - - 0.31s 24.6M
3.9 slim (glibc) all wheel 9.2s 0.27s 70M
3.9 slim (glibc) all - - 0.27s 70M
3.9 slim (glibc) gql wheel 3.9s 0.31s 26M
3.9 slim (glibc) gql - - 0.26s 26M

This quickstart demonstrates how to set up an asynchronous `gql` client using `AIOHTTPTransport`, define a GraphQL query, and execute it. It includes handling potential authentication headers and uses the recommended `async with client as session:` pattern for managing connections. Ensure you have `aiohttp` installed (e.g., `pip install "gql[aiohttp]"` or `pip install "gql[all]"`) for this example to run.

import asyncio
import os
from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport

async def main():
    # Replace with your GraphQL endpoint
    # For a real application, consider using environment variables for the URL and auth.
    graphql_url = os.environ.get('GRAPHQL_ENDPOINT_URL', 'https://countries.trevorblades.com/graphql')
    auth_token = os.environ.get('GRAPHQL_AUTH_TOKEN', '')

    headers = {}
    if auth_token:
        headers['Authorization'] = f'Bearer {auth_token}'

    # Select your transport
    transport = AIOHTTPTransport(url=graphql_url, headers=headers)

    # Create a GraphQL client
    client = Client(transport=transport, fetch_schema_from_transport=True)

    # Provide a GraphQL query (now returns GraphQLRequest object in v4+)
    query = gql(
        """
        query getContinents {
            continents {
                code
                name
            }
        }
        """
    )

    # Using `async with` on the client will start a connection
    # and provide a `session` variable to execute queries on this connection.
    async with client as session:
        # Execute the query (now accepts GraphQLRequest object in v4+)
        result = await session.execute(query)
        print(result)

if __name__ == "__main__":
    # If an asyncio event loop is already running, use this instead:
    # import nest_asyncio
    # nest_asyncio.apply()
    # asyncio.run(main())
    asyncio.run(main())