# Entity SEO API - Semantic SEO Tool for Any URL (`thodor/entity-seo-api`) Actor

Semantic SEO tool and entity extraction API: see what Google thinks your pages are about. Google Knowledge Graph entities with 0-100 scores for any URL. Free to try.

- **URL**: https://apify.com/thodor/entity-seo-api.md
- **Developed by:** [Thodor](https://apify.com/thodor) (community)
- **Categories:** SEO tools, Lead generation, AI
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $19.90 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

An **entity extraction API** that shows what Google thinks a page is about. Paste any URL and get back the **Google Knowledge Graph entities** Google associates with that page, each scored 0 to 100 and resolved to a human-readable name. This is Google's own read of the live page, not a re-analysis of text you paste in.

Run your page next to the competitor above you and the difference stops being a mystery: a scored list of concepts Google credits them for and not you. Scores update on recrawl, usually well before rankings move, so the same call doubles as a feedback loop: edit, re-run, see whether Google understood.

### 📋 How to find the entities Google associates with a page

1. Paste one or more page URLs into the **URLs** field. Bare domains work; `https://` is assumed.
2. Click **Start**.
3. Open the **Output** tab and click **Export** for JSON, CSV, Excel, or HTML.

### 🎁 So what do you get?

| 🧠 Every entity Google credits the page | 💯 0 to 100 confidence scores | 🏷️ Names, not codes |
| --- | --- | --- |
| 🆔 Stable Knowledge Graph IDs | 📝 Entity descriptions | 🖼️ The page's hero image |
| 🔗 About-this-site link | #️⃣ Entity count per URL | 🚫 Failed URLs logged, never billed |

### 🥊 What a competitor gap looks like

Real output from two pages competing for "tiktok comments scraper", one ranking #1 and one #6 (abridged, July 2026):

| Entity Google credits | Page ranking #1 | Page ranking #6 |
|---|---|---|
| web scraping | 60 | 65 |
| TikTok | 57 | 63 |
| **application programming interface** | **63** | **15** |
| **web crawler** | **37** | not credited |
| video recording | 38 | 58 |
| JSON | not credited | 19 |

Both pages get credit for the basics, so Google understood what they are. The gap is the content brief: the #1 page scores 63 on *API* and 37 on *web crawler*, the #6 page scores 15 and nothing. Own the #6 page? Those two rows are what to add. No claim that this is why #1 wins, but it is what you can measure, and scores shift on recrawl, so you also learn whether the fix landed.

### ⚖️ Compared to NLP and entity tools

| | This actor | Google Cloud NLP | TextRazor | InLinks / WordLift |
|---|---|---|---|---|
| Input | ✅ A URL | ❌ Text you supply | ⚠️ Text or URL | ⚠️ URL / your CMS |
| Entities from | ✅ Google's own page understanding | ❌ NLP run on your text | ❌ TextRazor's model | ❌ Their own model |
| Score | ✅ 0 to 100, comparable across pages | ⚠️ Relative salience | ⚠️ Relevance | ⚠️ Varies |
| Pricing | ✅ Pay per URL, no subscription | ⚠️ Usage-based, you crawl | ❌ From ~$200/mo | ❌ ~$39-49/mo |

An NLP model can only tell you what your text says; your text can be fine while Google's model of the page is not. From a real run: a page with "Exporter" in its headline scored 3/100 for *export*, because the title tag hadn't caught up with the copy. No text-analysis tool would have caught that.

### 🎯 Three things people run this for

| | How |
|---|---|
| 🥊 **Competitor gap briefs** | Run your page and theirs in one run, diff on `entity_id`. "Their page is somehow stronger" becomes "they score 63 on API, we score 15" |
| ⏱️ **Edit feedback before rankings move** | Edit the page, wait for the recrawl, re-run. Shifted scores mean Google understood the change, usually weeks before a rank tracker reacts |
| 📡 **Indexation monitoring** | Daily run on a [Schedule](https://docs.apify.com/platform/schedules). Any entities at all prove Google has crawled and classified the page, so the day an empty list turns into entities is the day a new page got picked up |

### 📥 Input

```json
{
  "urls": [
    "https://en.wikipedia.org/wiki/Marie_Curie",
    "https://www.nike.com/"
  ]
}
```

- `urls`: the pages to analyze. Any URL works, including ones you don't own: competitors, whole SERPs, your own site section

That is the whole input.

### 📤 Output

One record per URL, entities ranked highest confidence first. Failed URLs are never charged and never appear in the dataset; they land in the `FAILURES` record of the run's key-value store with reasons.

![Entity SEO API results in the Apify Console: one record per URL with entity count, hero image and about-this-site link](https://api.apify.com/v2/key-value-stores/LHcvkclm26dcJvwP1/records/google_entity_example_output_overview.png)

```json
{
  "url": "https://en.wikipedia.org/wiki/Marie_Curie",
  "entity_count": 34,
  "entities": [
    { "entity_id": "/m/053_d", "score": 100, "name": "Marie Curie", "description": "Polish-French physicist and chemist (1867–1934)" },
    { "entity_id": "/m/059x1", "score": 65, "name": "Nobel Prize", "description": "set of annual international awards" },
    { "entity_id": "/m/063wl", "score": 58, "name": "Pierre Curie", "description": "French physicist (1859–1906)" }
    // HIDDEN: 31 more entities, ranked by score
  ],
  "hero_image": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9Gc...",
  "about_this_site": "https://www.google.com/search?q=About+https://en.wikipedia.org/wiki/Marie_Curie&tbm=ilp"
}
```

> ⚠️ **Site-level entities show up on every page.** Your brand, platform, and domain score high on every URL of your site. Add a sibling page from your own site to the run and subtract what both share; what remains is the page's actual topic profile.

#### Fields

| Field | Description |
|---|---|
| `entity_count` | Number of entities returned for the page |
| `entities[].entity_id` | Google Knowledge Graph / Freebase ID, like `/m/053_d`. Stable across languages and phrasings, so diff on this, not on names |
| `entities[].score` | Google's confidence, 0 to 100. The page's main subject sits near 100 |
| `entities[].name`, `entities[].description` | Resolved via Wikidata. `null` for the few IDs with no public mapping |
| `hero_image` | The page's hero image, when Google has one |
| `about_this_site` | Google's "about this site" link, when available |

### ⚙️ Use it as an entity extraction API

Every run is an HTTP endpoint: POST the same JSON as the form and the records come back in the response body. The Python example is the full competitor gap analysis:

#### Python

```python
import requests

resp = requests.post(
    "https://api.apify.com/v2/acts/thodor~entity-seo-api/run-sync-get-dataset-items",
    params={"token": "YOUR_APIFY_TOKEN"},
    json={"urls": ["https://your-site.com/guide", "https://competitor.com/guide"]},
)

yours, theirs = resp.json()
covered = {e["entity_id"] for e in yours["entities"]}
for e in theirs["entities"]:
    if e["entity_id"] not in covered:
        print(f'{e["score"]:>3}  {e.get("name") or e["entity_id"]}')
```

Paste that gap list and your draft into an LLM and ask which sections to add or expand; the scores tell it what to prioritize.

#### Node.js

```javascript
import axios from "axios";

const { data } = await axios.post(
  "https://api.apify.com/v2/acts/thodor~entity-seo-api/run-sync-get-dataset-items",
  { urls: ["https://en.wikipedia.org/wiki/Marie_Curie"] },
  { params: { token: process.env.APIFY_TOKEN } }
);

data[0].entities.slice(0, 5).forEach((e) => console.log(e.score, e.name || e.entity_id));
```

#### curl

```bash
curl -X POST "https://api.apify.com/v2/acts/thodor~entity-seo-api/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://en.wikipedia.org/wiki/Marie_Curie"]}'
```

Swap `run-sync-get-dataset-items` for `runs` to fire async with a webhook. The `apify-client` SDK works too, in Python and JavaScript, and the n8n, Make, and Zapier integrations take the same input.

> 💡 **Tip:** no need to write the JSON by hand. Fill in the form on the Input tab, switch the editor from **Form** to **JSON**, and copy the result into your code.

### 🤖 Entity SEO for AI Overviews and LLM visibility

AI Overviews, ChatGPT, and Perplexity cite pages for what they are about at the entity level. The check is simple: does Google credit your pages for your brand, your products, your core topics? If not, a citation is unlikely however good the writing.

### 💰 How much does the Entity SEO API cost?

Billing is per URL analyzed, at the rate on the price card on this page. No subscription, no monthly minimum, and failed URLs are not charged.

### ❓ FAQ

**What is entity SEO?**
Optimizing the things a page is about rather than only the keywords on it. Google's model of a page is a set of Knowledge Graph entities with confidence scores: Marie Curie is `/m/053_d` whether the page writes "Marie Curie" or "Madame Curie". Being credited for the right entities with high scores is how a page ranks for a topic rather than a single phrase.

**Can I use the Entity SEO API for free?**
Yes. Registering on Apify comes with $5 of free platform credit every month, no credit card needed, enough for several hundred URLs.

**Why do some entities come back without a name?**
Some IDs have no public name or Wikidata mapping anywhere, so they come back bare with their score. A trick that resolves most: give the IDs and the page text to an LLM and ask what each likely refers to. You can also check which competing pages carry the same ID.

**Why does a page return no entities?**
Google doesn't associate entities with every URL; new, thin, or low-authority pages often have none yet. An empty list means the request succeeded and Google has no model of that page. That is an answer, not an error.

**Can this tell me when Google indexed my page?**
Not directly, but a daily schedule turns it into a monitor: the run where an empty list becomes entities brackets first classification to within a day, and the run where the profile shifts brackets a recrawl. Two limits: Google's serving cache refreshes about once a day, so resolution is one day at best, and only a *changed* profile proves anything; an unchanged one can still follow a recrawl.

**Does this tell me which keywords to target?**
No. It reports what Google credits a page for, not what people search for. Pick targets with keyword research; use this to check whether Google's model of your page matches, and to verify after a recrawl that edits registered.

**Is this legal?**
It returns publicly available entity classifications for URLs you choose to analyze and extracts no private data. Use the output to inform your own content decisions.

### 🛟 Support

Something not working, or a field missing? Message me in the Issues tab and I'll look into it quickly. I'm a solo dev, so don't hesitate.

- Thodor

# Actor input Schema

## `urls` (type: `array`):

The page URLs to analyze. For each URL you get the ranked Knowledge Graph entities Google associates with the page, each with a 0-100 confidence score. Bare domains work: https:// is assumed when the scheme is missing.

## Actor input object example

```json
{
  "urls": [
    "https://en.wikipedia.org/wiki/Marie_Curie"
  ]
}
```

# 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 = {
    "urls": [
        "https://en.wikipedia.org/wiki/Marie_Curie"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thodor/entity-seo-api").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 = { "urls": ["https://en.wikipedia.org/wiki/Marie_Curie"] }

# Run the Actor and wait for it to finish
run = client.actor("thodor/entity-seo-api").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "urls": [
    "https://en.wikipedia.org/wiki/Marie_Curie"
  ]
}' |
apify call thodor/entity-seo-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thodor/entity-seo-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EJWI6K70hv3VyAHvp/builds/AuYCdrx39j8Eq2Hr5/openapi.json
