Python client for strorefront graphql API

Topic summary

PythonクライアントでShopifyのStorefront GraphQL APIを呼ぶと、curlではHTTP 200で取得できるのに、Python(requests)だとHTTP 403になる問題が報告されている。

主な状況:

  • curlでは X-Shopify-Storefront-Access-Token を付け、Content-Type: application/graphql でクエリ文字列を送って成功。
  • Python例ではヘッダーが X-Shopify-Access-Token になっており、ボディも json={"query": ...} で送っているため、curlと送信形式・認証ヘッダーが一致していない可能性が示唆される。

提案/共有された対応:

  • gql + AIOHTTPTransport を使った動作例が共有され、ヘッダーに X-Shopify-Storefront-Access-TokenAccept: application/json を付けて .../api/{version}/graphql に送る形で成功している。

最新の動き:

  • 別の参加者が「directive に locations を提供しろ」というエラーに遭遇したと追記。

結論:

  • 403の根本原因やdirectiveエラーの解決はスレッド内では未解決のまま。
Summarized with AI on February 26. AI used: gpt-5.2.

Hi,

I am trying to build python client for storefront graphql API. I have tested the query using curl api.

curl -X POST https://mondayblues.myshopify.com/api/2019-07/graphql \
    -H 'X-Shopify-Storefront-Access-Token: ee466cb2b7130d7e2f3477e31b41194c' \
    -H 'Content-Type: application/graphql' \
    -H 'Accept: application/json' \
    -d ' {
  collections(first: 10) {
    edges {
      node {
        products(first: 10) {
          edges {
            node {
              description
              title
            }
          }
        }
      }
    }
  }
}
'

This gets the data with HTTP status code 200.

When I hit the same API with python client I get HTTP Status 403 with no response.

Do you have any sample client? Am I missing anything in the call?

import requests
import json

access_token = "ee466cb2b7130d7e2f3477e31b41194c"
url = "https://mondayblues.myshopify.com/api/2019-07/graphql"

collecctions_query = '''query {
  collections(first: 10) {
    edges {
      node {
        products(first: 10) {
          edges {
            node {
              description
              title
            }
          }
        }
      }
    }
  }
}'''

headers = {
    "X-Shopify-Access-Token": access_token,
    "Content-Type": "application/graphql",
    "Accept": "application/json"
    }

if __name__ == "__main__":
    # data={"query": collecctions_query}
    res = requests.post(url, json={"query": collecctions_query}, headers=headers)
    result = res.text
    print(result)

Thanks,

Mallik

Hi Mallik,

this is what I have right now and it seems to work:

from gql import gql, Client as GqlClient
from gql.transport.aiohttp import AIOHTTPTransport

class OAuthCredentialsProvider:
    """
    Abstraction around the OAuth access token that refreshes it when needed
    """
    def __init__(self):
        pass  # TODO: Implement

    def get_token(self) -> str:
        # TODO
        return "YOUR HARDCODED TOKEN"

class ShopifyGraphQLClient:
    gql: GqlClient

    def __init__(self, shop: str, credentials_provider: OAuthCredentialsProvider):
        self.shop = shop
        self.credentials_provider = credentials_provider
        self.api_version = "2020-07"

        self.gql = GqlClient(
            transport=self._create_transport(self.credentials_provider.get_token()),
            fetch_schema_from_transport=True,
        )

    def _create_transport(self, access_token: str) -> AIOHTTPTransport:
        return AIOHTTPTransport(
            url=f"https://{self.shop}/api/{self.api_version}/graphql",
            headers={
                "Accept": "application/json",
                "X-Shopify-Storefront-Access-Token": access_token,
            },
        )

if __name__ == "__main__":

    shop = "YOUR-STORE.myshopify.com"
    client = ShopifyGraphQLClient(shop, OAuthCredentialsProvider())

    query = gql(
        """
        { shop { name } }
        """
    )

    print(client.gql.execute(query))

Thanks JosXa.

Iam getting a error that u must provide locations for directive.