# Rank

`POST https://api.serpkite.com/v1/rank` · Credits: 7 for the top 100 (priced like /v1/search depth)

Where does a domain rank for a keyword? Returns the best organic position in the top N and every matching result.

A convenience endpoint for rank trackers: it fetches the top `num` organic results (default 100) and returns only what matched your `domain`, so you don't have to parse 100 results yourself. Subdomains match (`blog.example.com` counts for `example.com`).

For large keyword sets, queue them through [`POST /v1/batches`](https://serpkite.com/docs/endpoints/batches) with `endpoint: "search"` and `num: 100` at half price. See [Rank tracking](https://serpkite.com/docs/guides/rank-tracking).

## Request body

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `q` **required** | string |  | The keyword. |
| `domain` **required** | string |  | Domain to find, e.g. "example.com". Subdomains match. |
| `num` | integer | `100` | How deep to check. One of: `10`, `20`, `30`, `50`, `100`. |
| `country` | string | `us` | Country code. |
| `language` | string | `en` | Language code. |
| `location` | string |  | Canonical location for local rankings. |
| `device` | string | `desktop` | Device to search as. One of: `desktop`, `mobile`. |
| `max_age` | integer |  | Accept a cached result up to this many seconds old (half price). |

## Example request

cURL:

```bash
curl https://api.serpkite.com/v1/rank \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"best espresso machine 2026","domain":"example.com","country":"us"}'
```

TypeScript:

```ts
import { SerpKite } from "serpkite";

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.rank({ q: "best espresso machine 2026", domain: "example.com", country: "us" });
console.log(res.position, res.checked);
```

Python:

```python
from serpkite import SerpKite

sk = SerpKite()  # reads SERPKITE_API_KEY
res = sk.rank("best espresso machine 2026", "example.com", country="us")
print(res.position, res.checked)
```

## Response fields

| Field | Type | Description |
| --- | --- | --- |
| `request` | object | The normalised request, with defaults filled in: `endpoint`, `engine`, `q`, `country`, `language`, `location`, `num`, `page`, `device`, `autocorrect`… |
| `domain` | string | The normalised domain that was searched for. |
| `position` | integer \| null | Best organic position, or null if not in the checked results. |
| `matches[]` | array | Every matching result: `position`, `title`, `link`. |
| `checked` | integer | How many organic results were inspected. |
| `meta` | object | `request_id`, `credits_used`, `cached`, `cached_at`, `engine` (the provider that answered), `route` (provider attempts, see [Search providers](https://serpkite.com/docs/providers)), `latency_ms`, `parse_quality` (`ok`, `partial`, `empty`), `resolved_urls`. |

## Example response

```json
{
  "request": {
    "endpoint": "rank",
    "engine": "google",
    "q": "best espresso machine 2026",
    "country": "us",
    "language": "en",
    "num": 100
  },
  "domain": "example.com",
  "position": 1,
  "matches": [
    {
      "position": 1,
      "title": "The Best Espresso Machines of 2026, Tested and Reviewed",
      "link": "https://www.example.com/best-espresso-machines"
    },
    {
      "position": 14,
      "title": "Espresso grinder buying guide",
      "link": "https://www.example.com/grinders"
    }
  ],
  "checked": 100,
  "meta": {
    "request_id": "req_01J8ZK4M6Q2V7",
    "credits_used": 7,
    "cached": false,
    "engine": "google",
    "latency_ms": 1034,
    "parse_quality": "ok",
    "resolved_urls": true
  }
}
```

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | A parameter is missing or invalid. |
| 401 | `unauthorized` | The API key is missing, invalid or revoked. |
| 402 | `insufficient_credits` | Your balance is too low. Buy a pack or wait for the monthly free grant. |
| 429 | `rate_limited` | Too many requests per second for your plan. Retry after the Retry-After header. |
| 503 | `upstream_error` | Google could not be fetched or parsed. Not billed; retry after Retry-After. |

All errors: https://serpkite.com/docs/errors

## Notes

- Failed and empty searches are refunded, like every other endpoint.

## Related

- [Rank Tracker API](https://serpkite.com/apis/google-rank-tracker-api)
- [Rank tracking guide](https://serpkite.com/docs/guides/rank-tracking)
- [Free rank checker](https://serpkite.com/tools/rank-checker)