# Internet Asset Search API - Hosts, Ports, Certificates (`nabeelbaghoor/internet-asset-search-api`) Actor

Search internet-wide scan data for hosts, services, certificates and web properties by port, protocol, software, country and autonomous system, then read the full record: open ports, detected software, operating system, DNS names, geolocation and certificate chains. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/internet-asset-search-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Developer tools, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 asset returneds

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

## Internet Asset Search API - Hosts, Ports, Certificates

Query internet-wide scan data the way you would a database: every host running a protocol, every certificate issued to a name, every web property answering on a port, as rows.

### What it does

- **Searches the whole internet, not a list you supplied.** Hosts and the services on them, matched by the provider's query language, with the ports, protocols and software that matched lifted onto each row.
- **Keeps your query whole.** Whatever you write in the query field is preserved exactly and only extended with `and` clauses from the filter fields. It is never rewritten, because this query language expresses things no set of dropdowns could.
- **Filters for the things you would otherwise have to look up.** Port, protocol, country, autonomous system number and software product, each accepting several values.
- **Three asset kinds, one dataset.** Hosts by IP, certificates by SHA-256 fingerprint, and web properties by hostname and port.
- **Aggregation, which is a report as an API call.** Count a search by any indexed field, such as port, country or network operator, and get one row per distinct value with its count.
- **Rich host rows.** IP, city, province, country, latitude and longitude, ASN with name and description, every open port, every protocol, detected software, operating system, the DNS names resolving to it, and when it was last scanned.
- **Certificate rows that answer the actual question.** Subject and issuer common name and organization, every name on the certificate, the validity window, whether it is self-signed, and the key and signature algorithms.
- **An enrichment path for volume.** Host lookups can go through the provider's enrichment endpoint, which is built for high-volume use and does not consume standard credits on the plans that carry it.
- **Reads your credit balance first.** When you give an organization, the run logs the credits available before it starts spending them.
- **Keeps the misses.** An identifier the provider has no record of still produces a row saying so, and it is not charged for.

### Input

#### Find hosts running SSH on a non-standard port

```json
{
  "mode": "search",
  "query": "host.services: (protocol=SSH and not port: 22)",
  "countries": ["Germany"],
  "maxResults": 500
}
```

#### Everything a network operator is exposing on 443

```json
{
  "mode": "search",
  "autonomousSystems": ["15169"],
  "ports": ["443"],
  "software": ["nginx"],
  "maxResults": 1000
}
```

#### Look up hosts you already have

```json
{
  "mode": "hosts",
  "assets": ["8.8.8.8", "1.1.1.1"]
}
```

#### Count a search by country

```json
{
  "mode": "aggregate",
  "query": "host.services.protocol=POSTGRES",
  "aggregateField": "host.location.country",
  "buckets": 100
}
```

#### Certificates by fingerprint

```json
{
  "mode": "certificates",
  "assets": ["a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f809"]
}
```

### Example output

A search hit and an aggregation bucket.

```json
{
  "recordType": "searchHit",
  "assetId": "8.8.8.8",
  "ip": "8.8.8.8",
  "country": "United States",
  "countryCode": "US",
  "city": "Mountain View",
  "asn": 15169,
  "asName": "GOOGLE",
  "serviceCount": 3,
  "ports": [53, 443, 853],
  "protocols": ["DNS", "HTTP", "UNKNOWN"],
  "software": ["Google Frontend"],
  "dnsNames": ["dns.google"],
  "matchedPorts": [443],
  "matchedProtocols": ["HTTP"],
  "matchedServiceCount": 1,
  "lastUpdatedAt": "2026-09-01T04:22:11Z",
  "found": true
}
```

```json
{
  "recordType": "aggregate",
  "field": "host.location.country",
  "key": "United States",
  "count": 184203,
  "found": true
}
```

### Bring your own key

This actor calls an internet asset intelligence API with **your own account's personal access token**, managed in your provider account settings. Paste it into the personal access token field, or set it as the `DATA_API_KEY` environment secret. Add your organization id if you want the run to bill a specific organization and report its credit balance. Neither is ever written to the dataset or the log.

Without a token the run ends cleanly and tells you what to add, rather than failing.

### Pricing

Pay per result, platform usage included.

| Event | Price |
| --- | --- |
| Asset returned (host, certificate, web property) | $0.008 |
| Aggregation bucket returned | $0.002 |

Rows for identifiers the provider has no record of are never charged, and a search that matches nothing is never charged.

### FAQ

#### What is an internet asset search API?

An API over internet-wide scan data. The provider continuously scans the public internet and indexes what answers: which IP addresses have which ports open, what protocol and software is running on each, what TLS certificates they present, and what web properties they serve. Querying it answers questions like "every host in this country running this software version" without scanning anything yourself.

#### What query language does the search use?

The provider's own, CenQL. A query looks like `host.services: (protocol=SSH and not port: 22)`. Anything you type into the query field is sent as written; the port, protocol, country, ASN and software fields add `and` clauses onto it rather than replacing it.

#### Can I search by port and protocol without writing a query?

Yes. Leave the query field empty and fill in the ports, protocols, countries, autonomous systems or software fields. At least one of them, or a query, is required, because the provider will not answer a search for everything.

#### What comes back for a host?

The IP, city, province, country and coordinates, the autonomous system number with its name, description and country, every open port, every service protocol, detected software products, the operating system, DNS names resolving to the host, and when the provider last scanned it.

#### How do I look up a TLS certificate?

Use `mode: "certificates"` with SHA-256 fingerprints, one per line. Each row carries the subject and issuer common name and organization, all names on the certificate, the validity window, whether it is self-signed, and the key and signature algorithms.

#### What is a web property?

A hostname and port together, such as `platform.censys.io:80`. Rows carry the endpoints found on it, their paths, page titles, HTTP status codes and detected software.

#### How does the aggregation mode work?

It counts a search by one indexed field and returns one row per distinct value with its count, most common first. `host.services.port`, `host.location.country` and `host.autonomous_system.name` are the usual choices. It is the API form of the provider's report builder.

#### Does this scan anything itself?

No. It reads the provider's existing scan data through their API. Nothing in this actor sends traffic to the hosts it returns.

#### Do I need my own API key?

Yes. This actor is bring-your-own-key: it calls the provider with your account's personal access token, so you keep your own plan, credit balance and terms. There is no shared or bundled key. Some endpoints, including host enrichment and several historical routes, are limited to the provider's higher tiers.

#### How is the price calculated?

Per row stored. Hosts, certificates and web properties are $0.008, and aggregation buckets are $0.002. Rows saying something was not found cost nothing.

### Keyword map

internet asset search API, attack surface data API, host and port scan data API, TLS certificate lookup API, IP intelligence API, internet scanning data, exposed service discovery, ASN lookup API, shodan alternative API, security research data API, web property discovery, CenQL query API, external attack surface management data, port scan dataset

# Actor input Schema

## `mode` (type: `string`):

A run answers one question. Search runs a query across the provider's internet scan data. Hosts, certificates and web properties look up assets you already have. Aggregate counts a search by a field, which is the API form of a report. Fields belonging to another mode are ignored rather than causing an error.

## `apiKey` (type: `string`):

Your own account's personal access token for this provider, managed in your account settings. Bring your own key: nothing is shared between runs and the token is never written to the dataset or the log.

## `organizationId` (type: `string`):

Which organization to associate the request with and bill the credits to. Leave empty to use the token's default organization. Needed to read the credit balance at the start of a run.

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

A query in the provider's own query language, for example host.services: (protocol=SSH and not port: 22). Anything you write here is kept whole and only extended by the filters below, never rewritten. A field name the provider does not know is rejected rather than ignored.

## `ports` (type: `array`):

Only hosts with a service on any of these ports, one per line. Combined with the query above using and.

## `protocols` (type: `array`):

Only hosts running any of these service protocols, one per line, such as HTTP, SSH or POSTGRES. Sent upper cased, which is how the provider writes them.

## `countries` (type: `array`):

Only hosts located in any of these countries, one per line, written in full such as United States or Germany.

## `autonomousSystems` (type: `array`):

Only hosts in any of these autonomous systems, one ASN per line. This is how you scope a search to one network operator or hosting provider.

## `software` (type: `array`):

Only hosts running any of these software products, one per line, such as nginx or OpenSSH. Matched against the product name the provider detected on the service.

## `fields` (type: `array`):

Narrow what each search hit carries, one field path per line, such as host.ip. Leave empty for the full record. Omitting the service port, transport protocol and protocol fields means matched services are not returned at all.

## `assets` (type: `array`):

Assets to look up, one per line. An IP address for a host, a SHA-256 fingerprint for a certificate, or a hostname and port joined with a colon such as platform.censys.io:80 for a web property.

## `useEnrichment` (type: `boolean`):

Read hosts through the provider's enrichment endpoint instead of the standard host endpoint. It is built for high volume lookups and does not consume standard credits, but it is limited to the provider's higher tiers.

## `aggregateField` (type: `string`):

Which field to count a search by in aggregate mode, for example host.services.port, host.location.country or host.autonomous\_system.name. Only fields the provider indexes can be counted.

## `buckets` (type: `integer`):

How many distinct values an aggregation returns, most common first.

## `pageSize` (type: `integer`):

How many search hits to ask for per page. The provider's maximum is 100, and credits are consumed per page rather than per row, so a larger page is cheaper.

## `maxResults` (type: `integer`):

The most rows this run may store, and so the most it can charge for. A broad query can match millions of hosts, so this is the cap that keeps a run predictable.

## `requestsPerMinute` (type: `integer`):

How fast this run calls the provider. Lower it if your plan is rate limited more tightly than the default.

## `baseUrl` (type: `string`):

Overrides the API host. Only needed if the provider has given your account a different endpoint.

## Actor input object example

```json
{
  "mode": "search",
  "query": "host.services: (protocol=SSH and not port: 22)",
  "useEnrichment": false,
  "buckets": 50,
  "pageSize": 100,
  "maxResults": 100,
  "requestsPerMinute": 120
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record, alongside the query or identifier that produced it.

# 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 = {
    "query": "host.services: (protocol=SSH and not port: 22)"
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/internet-asset-search-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 = { "query": "host.services: (protocol=SSH and not port: 22)" }

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/internet-asset-search-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 '{
  "query": "host.services: (protocol=SSH and not port: 22)"
}' |
apify call nabeelbaghoor/internet-asset-search-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/internet-asset-search-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/cxVweaWZEf1EvPXm6/builds/AxCzBjuTj1sFHrFLb/openapi.json
