Published on July 31, 2025
With apps becoming more and more complex, web developers are increasingly favoring GraphQL as an alternative to REST APIs. While using REST APIs can lead to issues with over-fetching or under-fetching data, especially in content-heavy apps, GraphQL allows you to fetch only the data you need.
Python developers using web frameworks like Django or Flask often rely on REST APIs by default, but because GraphQL offers more control and a precise way to query data, this is starting to change.
This tutorial shows you how to work with a Python GraphQL client to query a live API using Flask and gql.
GraphQL is an API query language and runtime that lets you interact with your backend data through a schema. A GraphQL schema defines the types of data available (for example, user, post) and what fields they have (e.g., name, title). This schema creates relations between your data that feel graph-like, as it allows you to connect related data in a single query.
GraphQL may be seen as an evolution of REST: Rather than having to make multiple round trips for related data, you can query a single API and request data from multiple different resources in one API call.
Take the following example. A task that takes one query in GraphQL (using the query language to specify related resources) takes multiple requests in REST. You’ll also need to write code to aggregate all the data together at the end if you need to use it together.
GraphQL can also simplify your queries by making the shape of the response mirror the shape of your query. You don’t need to hunt through REST responses — you can just declare what you want to receive, and that’s the shape that will be returned.
While REST is often the default with frameworks like Django, Flask, or FastAPI, GraphQL provides a flexible alternative. Instead of hardcoding multiple routes and serializers scattered in different places in your code, you define a single schema in one place, with resolvers that handle GraphQL’s nested queries. GraphQL’s ability to nest queries is what allows it to reduce the number of API calls, improving performance.
Although Python is a dynamically typed language, most Python developers use type safety tools like type hints or Pydantic to improve code reliability. GraphQL’s type-safe schema aligns with this well and makes the shape of the API response predictable.
Python’s strengths in data analysis align with GraphQL’s ability to expose complex data that is well structured and sometimes deeply nested. Its introspection feature makes it easy for data scientists and automated systems to programmatically explore and understand complex data models.
GraphQL is popular and available as an option for most modern third-party APIs — for example, GitHub, Shopify, and Contentful. Any Python developers consuming these external APIs will benefit from having a clear GraphQL schema when working with structured content.
The following tutorial shows you how to query a GraphQL API using gql — a Python GraphQL client that simplifies sending GraphQL queries and handling responses. We’ll be using the Contentful GraphQL Content API for this example. Contentful has a headless CMS that lets you manage and deliver structured content to your website or app.
You will start by setting up a Flask server to act as a back end to consume the Contentful API. Then, once you’ve added some content to the Contentful web app, you’ll be able to perform a GraphQL query from your Flask code. Finally, you’ll learn how to filter your queries and paginate a response.
To be able to consume a GraphQL API with Python, you first need to build a web server to manage the HTTP requests. Flask is a lightweight web framework for Python that simplifies the process of building a server. It’s often used to build APIs, prototypes, dashboards, and anything that benefits from being fast and extensible.
First, create a new directory and then a virtual environment to host and activate the project:
Once inside the virtual environment, install Flask with the following command:
pip install Flask
Now, create an app.py
file with the following code:
The above code imports the Flask class, creates an instance of the app, and then defines a route for the home URL, which has a function that returns a string to welcome the user. You can run it by using the command flask run
and then visit http://127.0.0.1:5000
to see it in action.
To prepare the server to be able to send queries to the Contentful GraphQL API, install gql
, a Python GraphQL client:
pip install "gql[requests]"
Now that the server is up and running, you can head over to Contentful to add some content. Contentful will automatically update its GraphQL schema to reflect any content types and data that you add, allowing you to query your content through its GraphQL API.
Contentful makes it easy to serve your content over a GraphQL API. In Contentful, you do all your work inside a “space,” which is a project workspace that holds all the content related to your website or app. You can use your default space to host any content types you want to define, along with their individual fields. For example, a blog post content type might have a title field, along with slug and body fields. Each space gets a dedicated GraphQL endpoint automatically, sparing you the work of having to build it yourself and connect it to a database. Contentful also manages all of the infrastructure and serves your content from a high-speed global content delivery network (CDN), so you can automatically scale up or down according to your needs.
Head over to Contentful and start designing your content model by clicking on Content model from the top menu.
You will be creating an Article
content type with the following fields: title
, slug
, body
, and publishedAt
.
Click Design your content model to create a new content type.
Name the content type Article
and then click Create. Once it’s created, click Add field to start adding fields for your content type.
Now start adding the fields. title
and slug
will both be short text fields, body
will be a long text field, and publishedAt
will be a date.
Once you have added and configured all fields, click Save in the top right:
Back on the dashboard, you should now have an Article
content type with four fields.
Select Content from the top menu and click on Add entry to start adding some data for the Article
content type. Fill in the fields and select Publish, adding around six articles published on different dates so that you have some dummy data to play around with.
There’s no need to build a front end or even write server-side code just to test queries. If you’re curious about the GraphQL API and want to test something out, you can use a playground like Apollo Explorer, which gives you an interactive sandbox.
To be able to connect to and query the Contentful space, you will need a Contentful space ID and a Contentful Content Management API token, which you can find under API keys in Settings in the Contentful app.
Contentful actually sets up a GraphiQL playground for you automatically, so you can begin testing immediately. To connect to the playground, you can visit this URL, filling in your SPACE_ID and API_KEY, respectively:
https://graphql.contentful.com/content/v1/spaces/{SPACE_ID}/explore?access_token={API_TOKEN}
When you define a content type in Contentful (like Article), Contentful automatically generates two GraphQL fields:
article
— allows you to fetch a single item by ID
articleCollection
— allows you to fetch a list of entries of that content type
So, you can query to get all articles with only their titles using the following GraphQL query:
Now that you’ve tested that the Contentful GraphQL API is up and running, you can test out a few queries to make sure it works as you expect.
In a typical GraphQL query
, you use the query keyword followed by the name of the data type you want to fetch, adding an ID as an argument if you are querying a single entry. Then you state the fields you want to retrieve and define the shape of the response. For example, querying one specific article might look like this:
There are four main steps to run this query from your Python code:
Configure how the gql
library will communicate with the GraphQL API. In this example, we’re using a simple HTTP connection to transport this data rather than, say, a WebSocket. This requires configuring the GraphQL API endpoint and HTTP headers. These make use of a SPACE_ID and ACCESS_TOKEN, which you'll need to define as variables. (For security, these would normally be defined as environment variables.)
Set up the GraphQL client using this transport configuration.
Build the query, wrapping it in a gql()
function to make it processable by the gql
library. This query uses ENTRY_ID, so you’ll need to define that as a variable, too. To find the entry ID of one of the articles you created in Contentful, click on an article in the Content tab in Contentful, and select Info on the right-hand side.
Use client.execute(query)
to send the request and get the result.
You’ll also need to create a new route /article.
When accessed in the browser, this will trigger the GraphQL query to be built and executed.
Now, if you restart the server and visit http://127.0.0.1:5000/
article, you should see the result returns something like below:
If you want to filter results in GraphQL, the keyword where allows field-level filtering, which allows you to apply conditions to fields. For example, if you want to fetch articles published after a certain date, you can use where on the articleCollection, then specify the publishedAt field and pass in or specify a certain date to filter on:
The _gt
after publishedAt
is one of the comparison operators built into Contentful and stands for “greater than.”
Here are a few filtering operators that you can use in the Contentful GraphQL API. For each example, replace field with the actual field name you want to filter by, such as title or slug.
Operator | Purpose |
| Exact match |
| Checks if a field exists |
| Match if a field equals one of many |
| Checks if a field contains a substring |
| Greater than/less than |
Pagination is a great way to improve performance, especially when working with large datasets, as it breaks the retrieval of data into smaller, more manageable chunks. GraphQL offers a few pagination patterns, the most popular being offset-based and cursor-based. Contentful supports offset-based pagination using skip
and limit
.
With limit
, you can specify how many results to return in a single request:
With skip
, you can specify how many items to skip from the beginning.
On paginated websites, each page normally shows a fixed number of results (for example, 10 articles per page).
The skip
value tells GraphQL to ignore the first N results (depending on what page the user is on), so you only fetch the relevant articles for that page.
When using limit
and skip
out in the wild, you’d typically calculate them dynamically based on the current page and how many items per page you want to display, for example:
GraphQL can make your API calls more efficient and performant. Even so, there are some common pitfalls to avoid:
With GraphQL, it’s easy to get carried away and try to request too much data in one query. Eventually, this can have an impact on performance, especially if you’re nesting deeply or hitting multiple relations in a single call. Take the following query, for instance:
In the above example, the resolver may take time to tie all of the relations together. It’s better to fetch data in separate, targeted queries or use GraphQL fragments to manage the structure better. All in all, it’s best practice to keep your queries simple and request only what you need.
Another common mistake is using hardcoded variables in your GraphQL queries instead of variables. This can negatively impact maintainability and make the code less reusable. Using variables keeps the code cleaner and safer in the long run.
Here are some simple yet effective habits to follow when working with GraphQL to avoid straying into confusion:
Use a dedicated GraphQL client: Use tools like the one in the tutorial gql
to manage your queries, headers, and responses (rather than just using the requests
library).
Avoid repetition by using fragments: GraphQL fragments enable you to reuse parts of your query, improving the maintainability of your code.
Validate query results: Use tools like pydantic
, which enforces schema validation and can catch any errors you might otherwise miss.
Leverage a GraphQL playground before coding: Tools such as Apollo Explorer and GraphiQL allow you to test queries before writing any code. This can help you iron out any kinks and save time.
Avoid naming collisions: Use query aliases if you’re fetching the same type of field multiple times in one query.
Understand rate limits: Before querying, and especially when paginating or looping over results, be aware of the API provider’s rate limit. Some GraphQL APIs, like GitHub’s, apply rate limiting based on complexity. A few deeply nested queries could hit a rate limit much faster than you plan for. Fortunately, the API returns metadata about your remaining complexity budget, so you can monitor and adjust your usage.
Secure access tokens: Store any sensitive access tokens or IDs in environment variables. Don’t hardcode secrets in your scripts.
If you’re building a blog, marketing site, or other content-heavy app, why not consider Contentful?
It can give you structured content through a built-in GraphQL API served from a speedy global CDN.
There’s no need to build your own CMS, database, or GraphQL API. You can query content by type, locale, relationships, and more.
Subscribe for updates
Build better digital experiences with Contentful updates direct to your inbox.