---
title: Run a query with the Python SDK
description: >-
  Query a store with ShopifyQL from Python. Scaffold a notebook with the Shopify
  CLI, run queries in a notebook or a script, and work with the results as
  pandas or polars DataFrames.
source_url:
  html: 'https://shopify.dev/docs/apps/build/shopifyql/python-sdk/run-a-query'
  md: 'https://shopify.dev/docs/apps/build/shopifyql/python-sdk/run-a-query.md'
---

# Run a query with the Python SDK

Analyze a store's commerce data in Python, without building an app UI. In this tutorial, you'll run a ShopifyQL query with the ShopifyQL Python SDK, the `shopifyql` package, and then work with the results as a [pandas](https://pandas.pydata.org/) DataFrame. To learn when to reach for the SDK instead of the [GraphQL Admin API](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api), refer to [About the Python SDK](https://shopify.dev/docs/apps/build/shopifyql/python-sdk).

***

## What you'll learn

In this tutorial, you'll learn how to do the following:

* Set up a Python environment with the `shopifyql` SDK.
* Run a ShopifyQL query and read the results.
* Work with the results as a pandas DataFrame.
* Chart the results over time.

***

## Requirements

* Python 3.11 or later installed.
* A Shopify app that requests the `read_reports` access scope and has [Level 2 access to protected customer data](https://shopify.dev/docs/apps/launch/protected-customer-data), which ShopifyQL requires. The SDK authenticates as this app, so queries run against a store where it's installed. If you don't have an app yet, you'll scaffold one with the Shopify CLI in Step 1.

***

## Step 1: Set up your environment

The SDK authenticates as a Shopify app, so you run queries against a store where your app is installed. The fastest way to start is the Shopify CLI notebook template, which scaffolds an app wired to a Jupyter notebook with the SDK ready to use. You can also install the SDK into an app you already have.

### Scaffold a notebook with the Shopify CLI

The notebook template sets up a Shopify app with a preconfigured [Jupyter](https://jupyter.org/) environment running Python 3.11 or later and the `shopifyql` SDK installed. Scaffold it with the Shopify CLI:

## Terminal

```shell
shopify app init --template=https://github.com/Shopify/shopify-app-notebooks-template
```

Add the redirect URL `http://localhost:4545/callback` to your app's settings, and then start the app. The Shopify CLI logs in to your Partner account, connects the app, and writes your app credentials to a local `.env` file.

## Terminal

```shell
shopify app dev
```

These credentials are what the SDK uses to complete the OAuth flow in Step 2, so you authenticate from the notebook itself and never paste a token by hand.

### Install the SDK in an existing app

To add the SDK to an app you already have, install the package with pandas and polars support:

## Terminal

```shell
pip install "shopifyql[all]"
```

On this path, you construct the client yourself in Step 2, using your store's subdomain and the offline access token your app already holds. For how apps obtain and store that token, refer to [Offline access tokens](https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/offline-access-tokens).

***

## Step 2: Run a query

How you create the client depends on the path you chose in Step 1. Either way, pass the store's subdomain as `shop`, without the `.myshopify.com` suffix.

On the notebook template path, authenticate with `from_oauth`. The first time you run this, the SDK opens your browser to finish the OAuth flow on `http://localhost:4545/callback`, and then returns an authenticated client.

## Python

```python
from shopifyql import ShopifyQLClient


client = ShopifyQLClient.from_oauth(shop="your-store")


records = client.query(
    "FROM sales SHOW total_sales, orders TIMESERIES day SINCE -7d ORDER BY day ASC"
)
```

`from_oauth` reads the app's API key and secret from the `SHOPIFY_API_KEY` and `SHOPIFY_API_SECRET` environment variables, which the notebook template sets from `.env`. To call `from_oauth` outside the template, set both variables first, or pass `key` and `secret` to the call.

On the existing-app path, construct the client directly with the offline access token your app holds. Read the token from your app's session layer rather than hard-coding it, and then call the same query methods.

## Python

```python
from shopifyql import ShopifyQLClient


client = ShopifyQLClient(shop="your-store", access_token=access_token)
```

The query uses [`FROM` and `SHOW`](https://shopify.dev/docs/api/shopifyql/latest/syntax/from-and-show) to read the [`sales`](https://shopify.dev/docs/api/shopifyql/latest/schemas/sales_revenue/sales) dataset, returning total sales and orders, one row per day for the last 7 days. `client.query()` returns those rows as records. If the query is invalid or the response comes back without valid table data, then it raises a `ValueError` instead.

***

## Step 3: Work with the results as a Data​Frame

For analysis workflows, get the results directly as a pandas DataFrame:

## Python

```python
df = client.query_pandas(
    "FROM sales SHOW total_sales, orders TIMESERIES day SINCE -7d ORDER BY day ASC"
)
print(df.head())
```

***

## Step 4: Chart the results

The DataFrame is typed. `DAY_TIMESTAMP` columns come back as datetimes and `MONEY` columns as floats, so it plots without further conversion. Use the built-in pandas `plot()` method, which renders with [matplotlib](https://matplotlib.org/). Install matplotlib if it isn't already available:

## Terminal

```shell
pip install matplotlib
```

Query the data sorted from oldest to newest, and then plot the metric against the day:

## Python

```python
import matplotlib.pyplot as plt


df = client.query_pandas(
    "FROM sales SHOW total_sales TIMESERIES day SINCE -7d ORDER BY day ASC"
)


df.plot(x="day", y="total_sales", title="Total sales, last 7 days")
plt.show()
```

From here, you can join the DataFrame with other data or export it to a data warehouse.

***

## Next steps

In the SDK, results and errors are ordinary Python. A successful query returns records or a DataFrame, and a failed one raises an exception. The SDK doesn't surface the `parseErrors` list or the `shopifyqlCost` budget directly, so the next page covers the GraphQL Admin API model they map onto.

[Handle errors and budgets\
\
](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/errors-limits-and-performance)

[The GraphQL Admin API model for parse errors, rate limits, and query cost.](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/errors-limits-and-performance)

[ShopifyQL reference\
\
](https://shopify.dev/docs/api/shopifyql)

[Browse every dataset, metric, and dimension.](https://shopify.dev/docs/api/shopifyql)

[Build a sales dashboard with the GraphQL Admin API\
\
](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/build-a-sales-dashboard)

[Build reporting into an app instead of a notebook.](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/build-a-sales-dashboard)

***
