# GraphQL Endpoint Extractor (`datamule/graphql-endpoint-extractor`) Actor

Point at ANY GraphQL endpoint: send a raw query (+ optional variables & headers) and flatten the chosen data path into dataset rows plus a lossless raw object — or introspect the schema to discover its types. Works with public or token-gated GraphQL APIs. Pay per record.

- **URL**: https://apify.com/datamule/graphql-endpoint-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## GraphQL Endpoint Extractor

A **generic "point at any GraphQL endpoint" scraper**. There are plenty of instance-specific
GraphQL scrapers on the Store, but no generic runner that turns an *arbitrary* GraphQL API into a
dataset. Give this actor an endpoint URL and a raw GraphQL query (plus optional variables and
headers), tell it which part of the response to turn into rows, and it flattens the result into
clean dataset rows plus a lossless `raw` object — or introspect the schema to discover what an
endpoint exposes.

### What it does

- **Run any query** — send a raw GraphQL `query` (with optional `variables`) to any `endpoint`.
  The `{ data, errors }` envelope is handled for you: a pure-error response logs the errors and
  returns 0 records (no crash); a partial response keeps the data and notes the error count.
- **Pick your rows** — set `dataPath` (a dot-path from the response root, e.g.
  `data.characters.results` or `data.countries`) to select the array to flatten. Leave it empty
  and the actor auto-detects the first array under `data`; if there is no array, the whole `data`
  object is emitted as one row.
- **Introspect** — turn on **Introspect schema** to run the standard introspection query and get
  one row per schema type (name, kind, description, field count), so you can explore an unfamiliar
  endpoint before writing a query.
- **Flat + raw** — each element's scalar properties are spread to columns; the untouched element
  is kept in `raw`, so nothing is lost even though every schema is different.

### Example inputs

Rick and Morty characters (public, no auth) — nested array:

```json
{ "endpoint": "https://rickandmortyapi.com/graphql", "query": "{ characters { results { id name status species } } }", "dataPath": "data.characters.results" }
````

Trevorblades countries (public, no auth) — direct array, auto-detected:

```json
{ "endpoint": "https://countries.trevorblades.com/graphql", "query": "{ countries { code name capital currency } }" }
```

Parameterized query with variables:

```json
{ "endpoint": "https://rickandmortyapi.com/graphql", "query": "query($page:Int){ characters(page:$page){ results { id name } } }", "variables": { "page": 2 }, "dataPath": "data.characters.results" }
```

Discover the schema:

```json
{ "endpoint": "https://countries.trevorblades.com/graphql", "introspect": true }
```

### Pagination

GraphQL has no single pagination standard — cursor (Relay `edges`/`pageInfo`), offset, and
page-number schemes all differ per API. This is an honest **single-query runner**: pass your page
arguments directly in the `query` + `variables` (e.g. `characters(page: $page)` or
`search(first: 100, after: $cursor)`), run it per page, and use **Max records** to cap rows.

### Authentication

**None required** for public endpoints. For gated APIs, put your credentials in **Request
headers**, e.g. `{ "Authorization": "Bearer <token>" }` — header values are never logged.

### Output

One dataset item per selected element, with fixed meta columns:

- `_endpoint` — the queried endpoint.
- `_dataPath` — the resolved path the rows came from.
- `_index` — the row's position in the selected array.
- `_errors` — number of GraphQL errors on a partial response (null when none).
- …plus every property of the element as its own column, and `raw` = the complete original object.

In **Introspect** mode each row is a schema type: `name`, `kind`, `description`, `fieldCount`, `raw`.

A query that matches nothing (or a pure-error response) returns **0 items, not an error**.

### Pricing

**Pay per record** — you're charged one `record` event per row returned. A query that returns
nothing costs nothing.

### Notes

- Single POST per run (or two implicit for introspection). Handles GraphQL errors returned with
  either HTTP 200 or HTTP 400.
- Not affiliated with or endorsed by the GraphQL Foundation or any target API.

# Actor input Schema

## `endpoint` (type: `string`):

The URL of ANY GraphQL endpoint (the single POST URL, usually ending in /graphql). Examples: https://rickandmortyapi.com/graphql , https://countries.trevorblades.com/graphql , or your own API's GraphQL endpoint. For token-gated APIs, add the Authorization header in "Request headers" below.

## `query` (type: `string`):

The raw GraphQL query (or mutation) string to send, e.g. { characters { results { id name status species } } }. Required unless "Introspect schema" is enabled below. Use "Query variables" for parameterized queries. This is a single-query runner — put any pagination arguments (first/after/offset/page) directly in the query + variables.

## `variables` (type: `object`):

Optional GraphQL variables as a JSON object, e.g. {"page": 2, "filter": {"status": "Alive"}}. Reference them in the query with $page etc. Leave empty if your query takes no variables.

## `dataPath` (type: `string`):

Dot-path from the response root to the array (or object) to turn into rows, e.g. data.characters.results or data.countries. Leave EMPTY to auto-detect the first array under data (and if there is none, the whole data object becomes one row). Numeric segments index into arrays, e.g. data.search.edges.0.node.

## `introspect` (type: `boolean`):

When on, ignore the query and run the standard GraphQL introspection query instead, emitting one row per schema type (name, kind, description, field count) so you can discover what an endpoint exposes. Some servers disable introspection — then this returns 0 rows.

## `maxRecords` (type: `integer`):

Optional cap on the number of rows emitted from the response. Each emitted row is one billable record. Leave empty to emit every row the single query returns (GraphQL has no built-in pagination, so the server response already bounds this).

## `headers` (type: `object`):

Optional extra HTTP headers to send with the request, as a JSON object, e.g. {"Authorization": "Bearer <token>", "X-API-Key": "..."} for gated endpoints. Not required for public APIs. Header values are never logged.

## Actor input object example

```json
{
  "endpoint": "https://rickandmortyapi.com/graphql",
  "query": "{ characters { results { id name status species } } }",
  "dataPath": "data.characters.results",
  "introspect": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "endpoint": "https://rickandmortyapi.com/graphql",
    "query": "{ characters { results { id name status species } } }",
    "dataPath": "data.characters.results"
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/graphql-endpoint-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "endpoint": "https://rickandmortyapi.com/graphql",
    "query": "{ characters { results { id name status species } } }",
    "dataPath": "data.characters.results",
}

# Run the Actor and wait for it to finish
run = client.actor("datamule/graphql-endpoint-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "endpoint": "https://rickandmortyapi.com/graphql",
  "query": "{ characters { results { id name status species } } }",
  "dataPath": "data.characters.results"
}' |
apify call datamule/graphql-endpoint-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=datamule/graphql-endpoint-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "GraphQL Endpoint Extractor",
        "description": "Point at ANY GraphQL endpoint: send a raw query (+ optional variables & headers) and flatten the chosen data path into dataset rows plus a lossless raw object — or introspect the schema to discover its types. Works with public or token-gated GraphQL APIs. Pay per record.",
        "version": "0.1",
        "x-build-id": "tDaRewurOyx8dltLl"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/datamule~graphql-endpoint-extractor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-datamule-graphql-endpoint-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/datamule~graphql-endpoint-extractor/runs": {
            "post": {
                "operationId": "runs-sync-datamule-graphql-endpoint-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/datamule~graphql-endpoint-extractor/run-sync": {
            "post": {
                "operationId": "run-sync-datamule-graphql-endpoint-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "endpoint"
                ],
                "properties": {
                    "endpoint": {
                        "title": "GraphQL endpoint URL",
                        "type": "string",
                        "description": "The URL of ANY GraphQL endpoint (the single POST URL, usually ending in /graphql). Examples: https://rickandmortyapi.com/graphql , https://countries.trevorblades.com/graphql , or your own API's GraphQL endpoint. For token-gated APIs, add the Authorization header in \"Request headers\" below."
                    },
                    "query": {
                        "title": "GraphQL query",
                        "type": "string",
                        "description": "The raw GraphQL query (or mutation) string to send, e.g. { characters { results { id name status species } } }. Required unless \"Introspect schema\" is enabled below. Use \"Query variables\" for parameterized queries. This is a single-query runner — put any pagination arguments (first/after/offset/page) directly in the query + variables."
                    },
                    "variables": {
                        "title": "Query variables",
                        "type": "object",
                        "description": "Optional GraphQL variables as a JSON object, e.g. {\"page\": 2, \"filter\": {\"status\": \"Alive\"}}. Reference them in the query with $page etc. Leave empty if your query takes no variables."
                    },
                    "dataPath": {
                        "title": "Data path (row selector)",
                        "type": "string",
                        "description": "Dot-path from the response root to the array (or object) to turn into rows, e.g. data.characters.results or data.countries. Leave EMPTY to auto-detect the first array under data (and if there is none, the whole data object becomes one row). Numeric segments index into arrays, e.g. data.search.edges.0.node."
                    },
                    "introspect": {
                        "title": "Introspect schema (discovery)",
                        "type": "boolean",
                        "description": "When on, ignore the query and run the standard GraphQL introspection query instead, emitting one row per schema type (name, kind, description, field count) so you can discover what an endpoint exposes. Some servers disable introspection — then this returns 0 rows.",
                        "default": false
                    },
                    "maxRecords": {
                        "title": "Max records",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Optional cap on the number of rows emitted from the response. Each emitted row is one billable record. Leave empty to emit every row the single query returns (GraphQL has no built-in pagination, so the server response already bounds this)."
                    },
                    "headers": {
                        "title": "Request headers",
                        "type": "object",
                        "description": "Optional extra HTTP headers to send with the request, as a JSON object, e.g. {\"Authorization\": \"Bearer <token>\", \"X-API-Key\": \"...\"} for gated endpoints. Not required for public APIs. Header values are never logged."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
