---
title: Configure GraphQL malicious query protection via the API
description: Use the GraphQL API to configure query size and depth limits for your API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

### Tags

[ GraphQL ](https://developers.cloudflare.com/search/?tags=GraphQL) 

# Configure GraphQL malicious query protection via the API

Use the [Cloudflare GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/getting-started/) to gather data about your GraphQL API’s current usage and configure Cloudflare’s GraphQL malicious query protection to log or block malicious queries.

## Introduction

Query size is defined as the number of terminal fields (leaves) in the query, whereas query depth is the deepest level at which a leaf is present. For example, the size of this query will be reported as `4 (terminalField[1-4] all contribute to this counter)`, and the depth will be reported as `3 (terminalField3 and terminalField4 are at depth level 3)`.

GraphQL query

```

{

  terminalField1

  nonTerminalField1(filter: 123) {

    terminalField2

    nonTerminalField2 {

      terminalField3

      terminalField4

    }

  }

}


```

## Gather GraphQL statistics

Using the new `apiGatewayGraphqlQueryAnalyticsGroups` node in the Cloudflare GraphQL API, you can retrieve `apiGatewayGraphqlQuerySize` and `apiGatewayGraphqlQueryDepth` dimensions.

GraphQL query

```

query ApiGatewayGraphqlQueryAnalytics(

  $zoneTag: string

  $start: Time

  $end: Time

) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      apiGatewayGraphqlQueryAnalyticsGroups(

        limit: 100

        orderBy: [

          apiGatewayGraphqlQuerySize_DESC

          apiGatewayGraphqlQueryDepth_DESC

        ]

        filter: { datetime_geq: $start, datetime_leq: $end }

      ) {

        count

        dimensions {

          apiGatewayGraphqlQuerySize

          apiGatewayGraphqlQueryDepth

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBAggBwJYHECGAXMB3NUURoIAWwANgIrjRwB2aZUGSAxgM4AUAUDDACQAvAPa0wAFTQBzAFww2GCElqSe-eWggZZYpAFswqvmFoATbXoMBKGAG9VANyQ5It1b2GjOAMyRksEWRsYD3EpWUERUMkYAF9rO15EmCJUTBw8AiJSSmooOgYmVjYCIRAETjckmDI9JC0YAEYABibKpKEIE0gAIShZAG02qpT0LFx8QhJyKkgoAGUkATAAfQARAFE5gGEhpJG08cypnNnVsAQMYjXNnarEgF1dmB8-SECYEzTmfWXJMGBwupNAAaD5fCzLMj-cLGEyxIbxJ4sUq0DBPEwWWhsJAiNiuO57ZCjdITLLTXILJZPXj7MYZSbZGbQM4XYhPGJDDlJLnwmJAA&variables=N4IgXg9gdgpgKgQwOYgFwgFoHkByBRAfQEkAREAGhAGcAXBAJxrRACYAGFgNgFo2BWXgA44ARgDMqFoNR8+GCiBhQAJs3ZdeAtsJEBOSdNnyAvkA)

With the above query, you will get the following response:

Response

```

{

  "data": {

    "viewer": {

      "zones": [

        {

          "apiGatewayGraphqlQueryAnalyticsGroups": [

            {

              "count": 10,

              "dimensions": {

                "apiGatewayGraphqlQueryDepth": 1,

                "apiGatewayGraphqlQuerySize": 11

              }

            },

            {

              "count": 10,

              "dimensions": {

                "apiGatewayGraphqlQueryDepth": 1,

                "apiGatewayGraphqlQuerySize": 2

              }

            }

          ]

        }

      ]

    }

  },

  "errors": null

}


```

In the response example, Cloudflare observed 10 requests with depth 1 and size 11, and 10 requests with depth 1 and size 2 in the selected timeframe.

## Analyze GraphQL statistics

You can use the response to compute percentiles across the attributes and set a threshold on what is allowed. For example, you can use a simple heuristic like `1.5 * p99` for query size or depth.

Here is a simple Python script that will report query size and depth p-levels given the GraphQL API response output above (as a JSON file):

Python script

```

#!/usr/bin/env python3


import json

import numpy as np

import argparse


parser = argparse.ArgumentParser()

parser.add_argument("--response", help="Path to the API JSON response file with the apiGatewayGraphqlQueryAnalyticsGroups node", required=True)

args = parser.parse_args()

with open(args.response) as f:

    query_sizes = np.array([], dtype=np.uint16)

    query_depths = np.array([], dtype=np.uint8)

    data = json.load(f)['data']['viewer']['zones'][0]['apiGatewayGraphqlQueryAnalyticsGroups']

    for datapoint in data:

        query_sizes = np.append(query_sizes, [datapoint['dimensions']['apiGatewayGraphqlQuerySize']] * datapoint['count'])

        query_depths = np.append(query_depths, [datapoint['dimensions']['apiGatewayGraphqlQueryDepth']] * datapoint['count'])


    quantiles = [0.99, 0.95, 0.75, 0.5]

    print('\n'.join([f"Query size {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_sizes, quantiles))]))

    print('\n'.join([f"Query depth {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_depths, quantiles))]))


```

With the above query, you will get the following output:

```

./calculator.py --response=response.json

Query size 99th percentile is 11.0

Query size 95th percentile is 11.0

Query size 75th percentile is 11.0

Query size 50th percentile is 6.5

Query depth 99th percentile is 1.0

Query depth 95th percentile is 1.0

Query depth 75th percentile is 1.0

Query depth 50th percentile is 1.0


```

## Set limits on incoming GraphQL queries

API Shield customers now have three new fields available in custom rules:

* `cf.api_gateway.graphql.query_size` describes the size of a GraphQL query.
* `cf.api_gateway.graphql.query_depth` describes the depth of a GraphQL query.
* `cf.api_gateway.graphql.parsed_successfully` describes whether Cloudflare was able to parse the query. Presently, we run best-effort parsing, meaning we might not be able to parse some valid queries. This means that you must use a `and cf.api_gateway.graphql.parsed_successfully` filter in your custom rules when deploying GraphQL security rules.

For example, you can deploy the following rule via the API or the dashboard to block queries that are deeply nested and ask for over 30 fields.

```

(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)


```

Note

You are not able to configure which endpoints the GraphQL parsing runs on. Requests are parsed if they are targeting a path ending in `/graphql`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/graphql-protection/","name":"GraphQL malicious query protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/graphql-protection/api/","name":"Configure GraphQL malicious query protection via the API"}}]}
```
