# Importing a list of monitors

Onboarding many sites? Instead of one form per monitor, paste a list of addresses and HostTracker creates them in
one batch, all with the same settings. If you are moving from another monitoring service, the importer converts
its export into that list for you.

## Add a list of addresses

1. On **Sites**, click **Add Monitor** and pick the monitor type.
2. Above the address field, click **add list**.
3. Paste one address per line. To name a monitor, add the name after a comma:

   ```text
   https://shop.example.com/, Shop
   https://blog.example.com/
   api.example.com
   ```

   For Ping, enter hosts or IPs (`8.8.8.8, Google DNS`); for Port and SSL certificate checks, `host:port`
   (`mail.example.com:25`).
4. Set everything else once - interval, locations, validation, attached checks, alert and report subscriptions.
   Every monitor in the batch gets these settings.
5. Click **Save**. The list is checked first (**Checking the list...**) and nothing is created yet. You see:
   - how many lines **will be created**, how many will be **created disabled (over limit)** and how many are
     **rejected**;
   - each rejected line with its reason under **Next urls are invalid, blacklisted or already present**, and a
     **leave only valid urls** button.
6. If some lines were rejected, fix or remove them - or click **Save** again unchanged to create the valid lines
   anyway. A clean list is checked and submitted in one click.
7. The monitors are created by a background job (**Creating the monitors...**); follow it in the jobs indicator
   in the top bar. You can close the panel.

**add list** is available for Website/HTTPS, API, Page speed, Web content check, Ping, Port, DNSBL, Domain expiry,
SSL certificate expiry and Russian BL monitors. Transaction, Database, Counter, SNMP, Web Risk and Site crawl
monitors are created one at a time.

The counter under the box (**N of M lines**) shows how many lines you may paste in one batch: your plan's monitor
count, never more than 5000.

## Import from another service

1. In **add list** mode (or from the address field), click **import from another service**.
2. Choose the service. The panel shows the command to run with **your own** API key of that service - the key is
   never sent to HostTracker. For Uptime Kuma, export a backup (**Settings -> Backup -> Export**) instead.
3. Paste the JSON the command returned and click **Convert**. The service is detected automatically.
4. The monitors are grouped by the HostTracker type they map to. Click a group to load it into the list, then
   **Save** as above. Import one group (one type) per batch.

| Service | Command shown in the app |
|---|---|
| UptimeRobot | `curl -H "Authorization: Bearer YOUR_API_KEY" https://api.uptimerobot.com/v3/monitors` (the older v2 `getMonitors` response is accepted too) |
| Pingdom | `curl -H "Authorization: Bearer YOUR_API_TOKEN" https://api.pingdom.com/api/3.1/checks` |
| StatusCake | `curl -H "Authorization: Bearer YOUR_API_TOKEN" https://api.statuscake.com/v1/uptime` |
| Better Stack | `curl -H "Authorization: Bearer YOUR_API_TOKEN" https://uptime.betterstack.com/api/v2/monitors` |
| Site24x7 | `curl -H "Authorization: Zoho-oauthtoken YOUR_ACCESS_TOKEN" https://www.site24x7.com/api/monitors` |
| Uptime Kuma | Backup export file |

How monitors map:

| Source monitor | Becomes | Line format |
|---|---|---|
| HTTP(S) / URL / homepage / status / API / REST API | Website/HTTPS (**Fast Check Https**) | The URL |
| Keyword (and Better Stack keyword absence) | **Web content check**; one shared keyword is prefilled when the group uses a single keyword | The URL |
| Ping | **Ping check** | The host |
| Port / TCP, SMTP, POP3, IMAP, SSH | **TCP Port check** | `host:port` (standard port for the protocol when the export names none) |
| Site24x7 SSL certificate | **Certificate expiration** | The address |
| Site24x7 domain expiry | **Domain expiration** | The host |
| Heartbeat / push / cron, UDP, DNS, unknown types, entries without an address or port | Not imported - listed under **Not imported** with the reason | - |

:::caution[Keywords in UptimeRobot imports]
A batch shares one keyword. If the imported keyword monitors use different keywords, the app warns you: set one
keyword for the batch, then adjust individual monitors after the import.
:::

## Do it with the API or MCP

The API equivalent is the bulk create: shared `defaults` plus one item per monitor (item fields win). Validate
first, then submit (scope `monitor:write`):

```bash
BODY='{
  "defaults": { "type": "http", "interval": 300, "locations": { "pools": ["allworld"] }, "tags": ["imported"] },
  "items": [
    { "url": "https://shop.example.com/", "name": "Shop" },
    { "url": "https://blog.example.com/" },
    { "type": "ping", "url": "8.8.8.8", "name": "Google DNS" }
  ],
  "onOverlimit": "disable",
  "onDuplicate": "skip"
}'

# 1. Preview: one verdict per item, nothing written
curl -X POST https://api2.host-tracker.com/monitor/bulk-validate \
  -H "Authorization: Bearer $HT_TOKEN" -H "Content-Type: application/json" -d "$BODY"
# { "valid": 3, "invalid": 0, "wouldDisable": 0, "items": [ { "index": 0, "valid": true, "overlimit": "fits" }, ... ] }

# 2. Submit: 202 + job id (Idempotency-Key required)
curl -X POST https://api2.host-tracker.com/monitor/bulk \
  -H "Authorization: Bearer $HT_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-2026-09-29" -d "$BODY"
```

`bulk-validate` does not accept `callback` or `onError` - drop them from the preview body. Poll the job with
`GET /job/{id}` (see [Bulk operations](/monitors/bulk-operations/)); each item ends `created`, `createdDisabled`,
`skipped` or `failed`.

MCP: **`bulk_create_monitors`** with `itemsJson` (the items array) and `defaultsJson`; the first call validates
only, the second with `submit=true` creates. Intervals are in **seconds** (`{"interval":300}`). The tool always
uses the API defaults (`onOverlimit: "fail"`, `onDuplicate: "fail"`); use **`api_request`** with
`POST /monitor/bulk` to set them.

## What happens next

Every created monitor behaves like one made by hand and is picked up within about a minute. Subscriptions you set
in the form are applied to the new monitors when the job finishes. Adjust individual monitors afterwards, or use
[bulk edit](/monitors/bulk-operations/) to change many at once.

## Limits and gotchas

- **Plan limits still apply.** In the app, lines beyond your plan's monitor count are created **disabled** rather
  than refused. On the API, the default `onOverlimit: "fail"` fails those items; send `"disable"` to match the app.
- **Duplicates.** An address that already has a monitor of the same type is rejected (`duplicate_monitor`); on the
  API, `onDuplicate: "skip"` skips it instead.
- **Batch size.** More lines than your cap (`GET /account` -> `limits.maxBulkItems`, at most 5000) are refused
  with `422 too_many_items`; split the list.
- **One type per batch.** A pasted list becomes monitors of the type you picked; the API's `items` may mix types.
- The placeholder text in the list box mentions "up to 100 sites" - the real limit is the **N of M lines** counter.

## Related

- [Bulk operations](/monitors/bulk-operations/)
- [Copy an existing monitor](/monitors/copying/)
- [Monitor types](/monitors/monitor-types/)
- [Choosing a plan](/getting-started/choosing-a-plan/)
