# Keyword Intent SERP Classifier (`junipr/keyword-intent-serp-classifier`) Actor

Classify query intent using SERP evidence such as result types, dominant page formats, transactional modifiers, local packs, comparison pages, videos,...

- **URL**: https://apify.com/junipr/keyword-intent-serp-classifier.md
- **Developed by:** [junipr](https://apify.com/junipr) (community)
- **Categories:** SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $11.50 / 1,000 query snapshot classifieds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Keyword Intent SERP Classifier

Classify keyword intent from the result types, page formats, titles, snippets, and URLs visible in supplied SERP evidence. The actor produces transparent intent signals and confidence scores for content planning, paid-search research, and keyword segmentation.

### What you get

Each query becomes one dataset row with:

- primary and secondary intent;
- a normalized confidence score from 0 to 1;
- observed result types and dominant page formats;
- explicit local, transactional, and informational signal flags;
- a recommended content type based on the winning evidence class;
- source URL, evidence excerpt, issue code, scan time, and recommendation.

Supported primary labels include `local`, `transactional`, `commercial`, `informational`, `navigational`, and `mixed`. Optional deterministic rules may add named intent labels. The actor does not use an opaque model: scoring comes from visible words, result types, page formats, and the custom patterns you provide.

When `includeReport` is enabled, the default key-value store receives a Markdown summary, CSV rows, issue JSON, evidence JSON, and run metadata.

### Input choices

Use `serpResults` for structured query evidence. Each item can be a result record or an object containing `query` and `results`. Relevant fields include `resultType`, `title`, `snippet`, `url`, `pageFormat`, and `sourceUrl`.

Use `serpHtmlInputs` or `htmlInputs` for captured HTML. Every object should include its query. You may also provide explicit public URLs through `startUrls`; only those permitted URLs are fetched, and discovered links are not crawled.

Classification controls:

- `queries`: queries to classify.
- `customIntentRules`: objects with `name` or `intent`, a regular-expression `pattern`, and an optional numeric `weight`.
- `classifierMode`: `standard` uses the configured threshold; `strict` requires at least 0.65 confidence.
- `confidenceThreshold`: minimum winning score share before a single primary intent is emitted.
- `includeEvidenceUrls`: suppress source URLs when evidence locations should not be returned.
- `maxQueries`, `maxSnapshots`, `maxSignalsPerQuery`: bound analysis.
- `includeEvidence` and `includeRawSnapshots`: control excerpts and capped raw HTML retention.
- `maxChargeUsd`: stop before the next paid event would exceed the run ceiling.

### Example input

```json
{
  "queries": ["buy crm software", "how to organize sales leads"],
  "serpResults": [
    {
      "query": "buy crm software",
      "sourceUrl": "https://example.com/serp/buy-crm",
      "results": [
        { "resultType": "shopping", "title": "CRM pricing", "snippet": "Compare plans and buy", "url": "https://vendor.example/pricing" },
        { "resultType": "organic", "title": "Best CRM platforms", "snippet": "Product comparison", "url": "https://publisher.example/best-crm" }
      ]
    },
    {
      "query": "how to organize sales leads",
      "sourceUrl": "https://example.com/serp/organize-leads",
      "results": [
        { "resultType": "organic", "title": "How to organize sales leads", "snippet": "Step-by-step guide", "url": "https://publisher.example/guide" }
      ]
    }
  ],
  "classifierMode": "standard",
  "confidenceThreshold": 0.5,
  "includeEvidenceUrls": true,
  "maxQueries": 10,
  "maxSnapshots": 10,
  "maxSignalsPerQuery": 25,
  "includeReport": true,
  "maxChargeUsd": 35
}
```

### Example output

```json
{
  "recordType": "keyword_intent_serp_classifier",
  "recordName": "buy crm software",
  "issueCode": "keyword_intent_serp_classifier_ok",
  "severity": "low",
  "query": "buy crm software",
  "intentPrimary": "transactional",
  "intentSecondary": "commercial",
  "confidence": 0.545,
  "evidenceResultTypes": ["shopping", "organic"],
  "dominantPageFormats": ["product_or_commerce", "comparison_or_list"],
  "localIntentSignal": false,
  "transactionalSignal": true,
  "informationalSignal": false,
  "recommendedContentType": "product_or_pricing_page",
  "sourceUrl": "https://example.com/serp/buy-crm",
  "scannedAt": "2026-07-10T12:00:00.000Z"
}
```

### How scoring works

The actor combines query modifiers with the supplied SERP composition. Shopping and product evidence strengthens transactional intent. Reviews, comparisons, alternatives, and list pages strengthen commercial intent. Guides, explainers, tutorials, and videos strengthen informational intent. Map and local-pack evidence strengthens local intent. Official, login, support, and contact evidence can strengthen navigational intent.

Confidence is the winning score divided by all positive scores. If the winning share does not meet the configured mode and threshold, the row is labeled `mixed`. Custom rules are compiled defensively; an invalid optional pattern is ignored rather than executed as a guess.

If a query has no matching SERP evidence, the actor emits a diagnostic row with zero confidence. It never classifies intent from the query string alone on an evidence-free run. Access-denied or challenge pages receive a blocked diagnostic.

### Pay-per-event pricing

Platform usage pass-through is off. Every paid path charges before writing its associated output.

| Event | Price |
| --- | ---: |
| `actor-start` | $0.0350 |
| `query-snapshot-classified` | $0.0115 |
| `intent-signal-extracted` | $0.0115 |
| `intent-classification-emitted` | $0.0115 |
| `executive-report-generated` | $0.4000 |

The default maximum charge is $35. A zero ceiling prevents paid processing and output.

### Practical uses

- create intent buckets for editorial roadmaps;
- choose a page format that matches current SERP composition;
- separate local, transactional, commercial, and informational opportunities;
- compare classification changes across dated SERP captures;
- export evidence arrays for analyst review or downstream automation.

### Limits

Results reflect only the evidence provided. The actor does not estimate search volume, conversion probability, or future rankings. HTML parsers depend on explicit result markers; structured records are preferable for repeatable pipelines. Network inputs must be public HTTP(S) URLs and can be restricted with `allowedDomains`.

# Actor input Schema

## `startUrls` (type: `array`):

Optional explicit public URLs; private and non-HTTP targets are rejected.

## `sitemapUrls` (type: `array`):

Optional permitted public sitemap URLs.

## `htmlInputs` (type: `array`):

Deterministic HTML objects with sourceId, sourceUrl, and query context.

## `allowedDomains` (type: `array`):

Optional hostname allowlist for network fetches.

## `maxPages` (type: `integer`):

Overall HTML target cap.

## `maxDepth` (type: `integer`):

Fixed at zero because discovered links are not crawled.

## `includeEvidence` (type: `boolean`):

Include source evidence excerpts in dataset rows.

## `includeRawSnapshots` (type: `boolean`):

Store capped raw HTML in key-value storage.

## `requestDelayMs` (type: `integer`):

Delay between permitted public fetches.

## `timeoutMs` (type: `integer`):

Per-request timeout in milliseconds.

## `userAgentMode` (type: `string`):

Standard or compatibility request header.

## `serpResults` (type: `array`):

Query-linked result records or snapshot objects containing results.

## `queries` (type: `array`):

Queries to classify when matching SERP evidence is supplied.

## `serpHtmlInputs` (type: `array`):

Captured query-linked SERP HTML objects.

## `customIntentRules` (type: `array`):

Optional objects with name or intent, regex pattern, and weight.

## `includeEvidenceUrls` (type: `boolean`):

Allow source URLs in common evidence fields.

## `classifierMode` (type: `string`):

Deterministic evidence scoring profile.

## `confidenceThreshold` (type: `number`):

Minimum top-score share required before selecting a single primary intent.

## `maxQueries` (type: `integer`):

Maximum distinct queries classified.

## `maxSnapshots` (type: `integer`):

Maximum supplied snapshots processed.

## `maxSignalsPerQuery` (type: `integer`):

Maximum SERP evidence records scored per query.

## `maxChargeUsd` (type: `number`):

Maximum accepted PPE spend before paid output stops.

## `includeReport` (type: `boolean`):

Write Markdown, CSV, JSON evidence, and run metadata.

## Actor input object example

```json
{
  "startUrls": [],
  "sitemapUrls": [],
  "htmlInputs": [],
  "allowedDomains": [],
  "maxPages": 1,
  "maxDepth": 0,
  "includeEvidence": true,
  "includeRawSnapshots": false,
  "requestDelayMs": 250,
  "timeoutMs": 15000,
  "userAgentMode": "standard",
  "serpResults": [],
  "queries": [
    "best workflow software"
  ],
  "serpHtmlInputs": [],
  "customIntentRules": [],
  "includeEvidenceUrls": true,
  "classifierMode": "standard",
  "confidenceThreshold": 0.5,
  "maxQueries": 1,
  "maxSnapshots": 1,
  "maxSignalsPerQuery": 25,
  "maxChargeUsd": 35,
  "includeReport": true
}
```

# Actor output Schema

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

No description

## `report` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("junipr/keyword-intent-serp-classifier").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("junipr/keyword-intent-serp-classifier").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 '{}' |
apify call junipr/keyword-intent-serp-classifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,junipr/keyword-intent-serp-classifier"
        }
    }
}

```

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/Y3On51NEXcFhG3rdW/builds/AKZOoHlJpcSqHvGzt/openapi.json
