# Domains by Technology Analyzer (`opspilot.cc/domains-by-technology-analyzer`) Actor

This actor provides domains based on the technology they use. In addition to the list of domains, you will also get their technology profiles, the country and language they belong to, and other related data.

- **URL**: https://apify.com/opspilot.cc/domains-by-technology-analyzer.md
- **Developed by:** [wang wei](https://apify.com/opspilot.cc) (community)
- **Categories:** Lead generation, SEO tools
- **Stats:** 14 total users, 2 monthly users, 96.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Domains by Technology Analyzer — find sites by stack with auto-pagination

> Search 5,000+ technologies (Shopify, WordPress, nginx, Google Analytics, jQuery, React…) and pull a clean list of domains that use them, with optional country filtering and automatic cursor pagination up to 1,000 results per run.

### Why Use This Actor

| Problem | How This Actor Solves It |
|---|---|
| Need a prospect list of every Shopify store in the US? | Search `Shopify` + filter `country: US` in one run. |
| Need more than 100 results? | Set `limit` up to 1,000 — the Actor cursor-paginates upstream results automatically so you get a single, de-duplicated, ordered list. |
| Don't know the exact casing of a technology? | Case is normalized via an 800+ alias table: `wordpress` → `WordPress`, `GA` → `Google Analytics`. |
| Need to resume a previous run? | Use `offset` to skip the first N upstream items. |

### What You Get

For every matched domain you receive:

- **Identity**: `domain`, `title`, `description`, `metaKeywords`
- **Signals**: `domainRank`, `lastVisited`, `countryIsoCode`, `languageCode`, `contentLanguageCode`
- **Contact**: `phoneNumbers[]`, `emails[]`, `socialGraphUrls[]`
- **Stack**: full `technologies{}` object as detected upstream
- **Provenance** (`_*` fields): the query echo, total upstream count, page count, and how many items this run collected — so you can detect partial vs. complete runs.

### Quick Start

#### 1. Run with Example Input

```json
{
  "technologies": "Shopify\nWordPress",
  "country": "US",
  "limit": 250
}
```

Returns up to 250 US domains using Shopify OR WordPress.

#### 2. Export Your Results

- Open the run in [Apify Console](https://console.apify.com/actors/).
- Click the **Dataset** tab → **Export** → JSON / CSV / Excel.
- Or fetch the API: `GET https://api.apify.com/v2/acts/<ACTOR_ID>/runs/<RUN_ID>/dataset/items`

### Input Reference

#### Top-Level Structure

```json
{
  "technologies": "Shopify\nWordPress\nWooCommerce",
  "country": "US",
  "limit": 500,
  "offset_token": ""
}
```

#### `technologies` — Technologies

| Required | Type | Default | Description |
|---|---|---|---|
| Yes | string (textarea) | — | One technology per line, or comma-separated. Case-insensitive (normalized via the built-in alias table). **Up to 10 per run.** |

**Examples**:

```
Shopify
WordPress
Google Analytics
nginx
WooCommerce, jQuery, React
```

#### `country` — Country Filter

| Required | Type | Default | Description |
|---|---|---|---|
| No | string | empty (all countries) | ISO-3166-1 alpha-2 code: `US`, `GB`, `DE`, `CN`, `JP`, `BR`, etc. Leave empty to search worldwide. |

#### `limit` — Result Limit

| Required | Type | Default | Min | Max | Description |
|---|---|---|---|---|---|
| No | integer | 100 | 1 | 1000 | How many domains to collect. The Actor cursor-paginates upstream results automatically — setting `limit: 500` will fetch 5 upstream pages if needed. |

#### `offset_token` — Resume From Cursor

| Required | Type | Default | Description |
|---|---|---|---|
| No | string | empty | Opaque base64 cursor returned by a previous run. Paste the value of `_lastOffsetToken` from a SUMMARY record to resume that run from where it left off. Leave empty to start fresh. |

### Output Reference

#### Domain Object — one row per matched domain

| Field | Type | Description |
|---|---|---|
| `domain` | string | The root domain, e.g. `example-store.com`. |
| `title` | string|null | `<title>` tag content. |
| `description` | string|null | `<meta name="description">` content. |
| `metaKeywords` | string|null | `<meta name="keywords">` content. |
| `domainRank` | number|null | Upstream rank score (lower = more popular). |
| `lastVisited` | string|null | ISO timestamp of last crawl visit. |
| `countryIsoCode` | string|null | ISO-3166-1 alpha-2 country of the IP. |
| `languageCode` | string|null | Detected site language. |
| `contentLanguageCode` | string|null | `<meta http-equiv="content-language">` value. |
| `phoneNumbers` | string\[] | Phone numbers scraped from the page. |
| `emails` | string\[] | Email addresses scraped from the page. |
| `socialGraphUrls` | string\[] | URLs to the site's social profiles. |
| `technologies` | object | Map of detected technologies on this domain. |
| `_query` | object | Echo of the input that produced this row (technologies, limit, offset, country). |
| `_totalCount` | number | Total matching domains upstream (may be > `_collected`). |
| `_pagesFetched` | number | How many upstream pages this run pulled. |
| `_collected` | number | Items actually pushed in this run (= `limit`, or fewer if upstream had less). |
| `_lastOffsetToken` | string|null | Opaque cursor to pass into the next run's `offset_token` to continue paginating. `null` when upstream has no more pages. |

#### Run Summary

Stored under the `SUMMARY` key in the default key-value store. Shape:

```json
{
  "ok": true,
  "query": { "technologies": ["..."], "normalizedTechs": ["..."], "limit": 500, "offset": 0, "country": "US" },
  "result": { "totalCount": 12834, "collected": 500, "pagesFetched": 5, "lastOffsetToken": "eyJ...", "hasMore": true },
  "paying": false,
  "freeRunsToday": 2,
  "apiRequests": 5,
  "completedAt": "2026-07-20T12:00:00.000Z"
}
```

### Pagination — How It Works

Each run returns **exactly 100 domains**. To get the next 100, run again with `offset = previous_nextOffset`.

```
Run 1: offset=0   → 100 items (1-100),  _nextOffset: 100
Run 2: offset=100 → 100 items (101-200), _nextOffset: 200
Run 3: offset=200 → 100 items (201-300), _nextOffset: 300
...
Run 99: offset=9800 → 100 items (9801-9900), _nextOffset: null (exhausted)
```

When `_nextOffset` is `null`, upstream has no more matches and you've finished.

#### Hard ceiling: 9900 items per query

The upstream API enforces `offset + limit <= 10000` and rejects anything above (`Invalid Field: 'limit'`). With `limit` locked at 100, the maximum reachable offset is **9900** — that's 99 pages × 100 = 9,900 domains per `(technologies, country, last_visited)` query.

To go deeper:

- **Refine your query**: add a `country` filter to scope results to a single market.
- **Split technologies**: search `Shopify` in run 1, `WooCommerce` in run 2, etc.
- **Tighten `last_visited`**: the Actor defaults to "visited this calendar year"; older results need a different filter (currently hardcoded — let us know if you need a date range input).

#### Empty-page handling

If a run returns 0 items (offset past the end), the Actor returns an empty dataset with `_nextOffset: null` and `hasMore: false`. No upstream call is made when `offset > 9900`.

### Pricing & Limits

- **Free tier**: 5 runs/day (capped via Actor-scoped KV store).
- **Hard cap per run**: 100 domains.
- **Hard cap on technologies per run**: 10.
- **Max pages per query**: 99 (offset 0 → 9800, yielding 9,900 items total). Beyond that, refine your query.
- **Filter**: `lastVisited` is restricted to the current calendar year by default (results stay fresh).

### FAQ

**Q: Why do I get fewer results than `limit`?**
A: Upstream simply doesn't have that many matches for your query. Check `_totalCount` in the output or `result.totalCount` in SUMMARY — that's the real upstream count.

**Q: How do I get more than 100 results?**
A: Run the Actor again with `offset` set to the value of `_nextOffset` from the previous run's SUMMARY (or any dataset row's `_nextOffset` field). Example: run 1 returns 100 items with `_nextOffset: 100`. Run 2 uses `offset: 100` to get items 101-200. Repeat until `_nextOffset` is `null`.

**Q: Does case matter in `technologies`?**
A: No. Input is lowercased and looked up in the alias table (800+ entries). `wordpress`, `WordPress`, and `WORDPRESS` all resolve to canonical `WordPress`.

**Q: Does the free tier reset at midnight UTC?**
A: Yes — the counter is keyed by `YYYY-MM-DD` (UTC).

**Q: Why is `_collected < limit` even though `_totalCount > limit`?**
A: You ran out of free quota mid-pagination, OR upstream returned pages shorter than `limit`. Use the API (`apify call`) or a paid tier to avoid the free-tier block.

### Support

- **Console run page**: open the run for live logs + retry options.
- **Email**: sam.wang0420@gmail.com (errors auto-notified via Resend).

### License

MIT License — free to use and modify.

# Actor input Schema

## `technologies` (type: `string`):

Technology names to search for, one per line or comma-separated.

Examples:
WordPress
Google Analytics
Shopify, WooCommerce
nginx

Case is normalized automatically. Up to 10 technologies per run.

## `country` (type: `string`):

Optional ISO-3166-1 alpha-2 country code to filter results.

Examples: US, GB, DE, CN, JP, BR

Leave empty to search all countries.

## `offset` (type: `integer`):

Skip the first N upstream items. Default 0.

To paginate: first run returns 100 items with `_nextOffset: 100`. Second run sets `offset: 100` to get items 101-200, etc.

Maximum offset: 9900 (upstream enforces `offset + 100 <= 10000`).

## Actor input object example

```json
{
  "technologies": "WordPress",
  "offset": 0
}
```

# Actor output Schema

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

Array of domain objects, one per match. Use the dataset URL to fetch or stream the full list.

## `summary` (type: `string`):

Run-level summary: query, total upstream count, collected count, pages fetched, API request count, free-tier usage. Stored as the SUMMARY key in the default key-value store.

# 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 = {
    "technologies": "WordPress"
};

// Run the Actor and wait for it to finish
const run = await client.actor("opspilot.cc/domains-by-technology-analyzer").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 = { "technologies": "WordPress" }

# Run the Actor and wait for it to finish
run = client.actor("opspilot.cc/domains-by-technology-analyzer").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "technologies": "WordPress"
}' |
apify call opspilot.cc/domains-by-technology-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=opspilot.cc/domains-by-technology-analyzer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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