---
title: Look up an IP address
description: Look up an IP address's location and network through looot's ip.lookup job, and enrich it with company and person signals through ip.enrich.
---

Two jobs cover IP addresses. `ip.lookup` gives back country, continent and ASN details and runs
free on its one provider. `ip.enrich` adds company and person signals where they exist, and costs
more.

## What it costs

```json MCP
search {"filters": {"capability": "ip.lookup"}, "prefer": "cheapest"}
```

On 2026-09-28 `ip.lookup` priced $0 per call on its one provider, and the one `ip.enrich`
provider listed priced around $0.28 per call. Read the live numbers before you run `ip.enrich` on
more than a handful of addresses.

1. **Look up the IP**

    Send `ip`:

    <CodeGroup>

    ```json MCP
    run {"endpointId": "job:ip.lookup", "input": {"ip": "8.8.8.8"}, "idempotencyKey": "ip-lookup-1", "fallback": true}
    ```

    ```bash REST
    curl -s "https://api.looot.ai/v1/runs?wait=20" \
      -H "Authorization: Bearer $LOOOT_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "endpointId": "job:ip.lookup",
        "input": {"ip": "8.8.8.8"},
        "idempotencyKey": "ip-lookup-1",
        "fallback": true
      }'
    ```

    ```bash CLI
    looot run job:ip.lookup --input '{"ip": "8.8.8.8"}' --wait
    ```

    </CodeGroup>

    :::note
    looot 1.1.0 does not accept `--fallback` on `looot run`. The CLI call above tries one provider.
    :::

    This job has no [`normalized`](/concepts/normalized-output) map yet: read the country, continent and ASN fields from `result`.

2. **Enrich it, if you need company or person signals**

    `ip.enrich` costs more, so quote it first (step above) and use it only when `ip.lookup` is not
    enough:

    ```json MCP
    run {"endpointId": "job:ip.enrich", "input": {"ip": "8.8.8.8"}, "idempotencyKey": "ip-enrich-1", "fallback": false}
    ```

3. **One field only**

    `ip.lookup.field` returns a single field of IP information, not the whole object, for when that
    is all you need. Search for it and read [`jobInputs`](/concepts/job-inputs) before you run it, since its shape differs from
    `ip.lookup`:

    ```json MCP
    search {"filters": {"capability": "ip.lookup.field"}}
    ```

## What the answer looks like

| Field | What it is |
| --- | --- |
| `status` | `completed`, `failed`, `queued`, `running` |
| [`outcome`](/concepts/outcomes) | `hit`, `weak`, `miss`, `error`, `rejected`, `skipped` or `pending` |
| [`servedProviderId`](/concepts/served-provider) | the provider that answered |
| `actualCost` | what this run charged, $0 on `ip.lookup`'s free provider |
| `route.summary` | fallback runs only |

## On a miss or error

- A private or bogon IP: the provider can answer with a flag saying so and no location data;
  treat that as a valid result, not a miss.
- A malformed IP never reaches a provider: the run fails with [`validation_error`](/errors/rest-errors#validation_error) and charges
  nothing.
- [`insufficient_balance`](/errors/rest-errors#insufficient_balance) on `ip.enrich`: the run is blocked and not charged. Use [`top_up`](/mcp-tools/top-up), then
  retry with a new [`idempotencyKey`](/concepts/idempotency).

<Related />
