Skip to content
API

Search, alerts & utilities

Health and auth checks, search, Actor alerts, bookmarks, templates, and integrations.

Cross-cutting endpoints: health and auth checks, global search, Actor alerts, bookmarks, Actor templates, the support form, and third-party integrations. Paths are relative to https://api.scrape.ly.

Endpoints require authentication unless noted.

Health check

GET/health

Liveness probe. No authentication required. The path has no /v2 prefix.

.bash
curl https://api.scrape.ly/health

The response is a bare JSON object with no data wrapper:

.json
{ "status": "ok", "timestamp": "2026-01-01T00:00:00.000Z" }

When the service is unhealthy it returns 503 with { "status": "unhealthy" }. Check the status code; the body carries no other details.

Rate limited to 60 requests per minute per IP address, lower than the general API limit, so size monitoring intervals accordingly. Use GET /v2/auth/check when you also need to verify a token.

Auth check

GET/v2/auth/check

Lightweight identity probe. The response is only authenticated and, when signed in, userId, with no data wrapper.

.bash
curl "https://api.scrape.ly/v2/auth/check" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

With a valid token:

.json
{ "authenticated": true, "userId": "uSeRiDeXaMpLe123" }

Without an Authorization header:

.json
{ "authenticated": false }

An invalid or revoked token is not treated as anonymous: it returns 401 token-not-valid.

GET/v2/auth/check
GET/v2/search

Searches your own Actors, runs, and tasks.

.bash
curl "https://api.scrape.ly/v2/search?q=my-actor&limit=10" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
Query paramTypeDefaultDescription
qstring—Search term (substring match). Empty or omitted returns empty arrays.
limitnumber10Max results per resource type (max 50).

What q matches:

  • Actors: name, ID, username, or title. Newest-modified first.
  • Runs: run ID, Actor name, or Actor username. Newest first.
  • Tasks: task name, task ID, or Actor name. Newest-modified first.
.json
{
  "data": {
    "actors": [
      {
        "id": "actor-uuid",
        "name": "my-actor",
        "username": "jane",
        "title": "My Scraper",
        "description": "...",
        "isPublic": true,
        "pictureUrl": null,
        "createdAt": "2026-01-01T00:00:00.000Z",
        "modifiedAt": "2026-08-01T00:00:00.000Z"
      }
    ],
    "runs": [
      {
        "id": "run-uuid",
        "actId": "actor-uuid",
        "status": "SUCCEEDED",
        "startedAt": "2026-08-01T00:00:00.000Z",
        "finishedAt": "2026-08-01T00:05:00.000Z",
        "usageTotalUsd": 0.12,
        "usageTotalNd": 120000000,
        "actorName": "my-actor",
        "actorUsername": "jane"
      }
    ],
    "tasks": [
      {
        "id": "task-uuid",
        "name": "daily-crawl",
        "actId": "actor-uuid",
        "actorName": "my-actor",
        "actorUsername": "jane",
        "createdAt": "2026-07-01T00:00:00.000Z",
        "modifiedAt": "2026-08-01T00:00:00.000Z"
      }
    ]
  }
}

A run's usageTotalUsd is in US dollars. usageTotalNd is the same amount in nanodollars ($1 = 1_000_000_000).

GET/v2/search?q=actor&limit=3

Actor alerts

Alerts watch the runs of an Actor you can access (you own it, or it's public) and notify you by email and/or in the dashboard when a condition is met. They are checked after each run finishes.

  • Alerts on your own Actor fire for every run of it. Alerts on someone else's public Actor fire only for your runs.
  • Each alert notifies at most once per minute.
  • Email needs a saved notification email and counts toward your weekly email quota. See Notifications.

List alerts

GET/v2/actors/{actorId}/alerts

Returns your alerts for that Actor, newest first. The envelope is { "alerts": [...] }, not { "data": ... }. Boolean fields come back as 1 / 0.

curl "https://api.scrape.ly/v2/actors/{actorId}/alerts" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
GET/v2/actors/{actorId}/alerts

Create an alert

POST/v2/actors/{actorId}/alerts

Returns 201 with { "data": <alert> }.

.bash
curl -X POST "https://api.scrape.ly/v2/actors/{actorId}/alerts" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Slow run",
    "triggerType": "METRIC",
    "metric": "DURATION",
    "condition": "GREATER_THAN",
    "value": 600,
    "notifyEmail": true,
    "notifyWeb": true
  }'
Body fieldTypeRequiredDescription
namestringYesDisplay name.
triggerTypestringYesMETRIC or DATASET_FIELD_STATS.
metricstringFor METRICA metric from the table below, or STATUS.
conditionstringFor comparisonsGREATER_THAN, LESS_THAN, or EQUALS.
valuenumberFor comparisonsThreshold.
statusValuestringWith metric: "STATUS"Run status to match, such as FAILED, TIMED-OUT, ABORTED, or SUCCEEDED.
datasetFieldstringFor dataset triggersTop-level field name; letters, digits, and underscores only.
datasetFieldStatisticstringFor dataset triggersFILLED_PERCENTAGE, AVG_VALUE, MIN_VALUE, MAX_VALUE, or AVG_LENGTH.
enabledbooleanNoDefault true.
notifyEmailbooleanNoDefault true.
notifyWebbooleanNoDashboard notification. Default true.

Only name and triggerType are validated. An alert with an unknown metric, statistic, or condition, or with missing fields, is saved but never fires.

Status alerts: set metric to STATUS and statusValue to a run status. condition and value are ignored.

Metric alerts compare one run metric with value:

MetricUnit
DURATIONSeconds
USAGERun cost in USD
COMPUTE_UNITSCompute units
NUMBER_OF_RESULTS, NUMBER_OF_DATASET_ITEMSItems in the default dataset
NUMBER_OF_DATASET_FIELDSFields in the build's dataset schema
DURATION_PER_RESULTSeconds per dataset item
COST_PER_RESULTUSD per dataset item
MAX_CPU_USAGEPeak CPU usage
MAX_MEMORY_USAGEPeak memory, bytes
SIZE_OF_KEY_VALUE_STOREBytes
NUMBER_OF_REQUESTS_HANDLEDHandled request queue requests
NUMBER_OF_DATASET_READS, NUMBER_OF_DATASET_WRITESOperations
NUMBER_OF_KV_STORE_READS, NUMBER_OF_KV_STORE_WRITES, NUMBER_OF_KV_STORE_LISTSOperations
NUMBER_OF_REQUEST_QUEUE_READS, NUMBER_OF_REQUEST_QUEUE_WRITESOperations
NUMBER_OF_REQUESTSRequest queue reads + writes
SIZE_OF_INTERNAL_DATA_TRANSFER, SIZE_OF_EXTERNAL_DATA_TRANSFERBytes

Dataset field alerts (DATASET_FIELD_STATS) compute a statistic over one field of the run's default dataset, sampling up to 1,000 items, and compare it with value. FILLED_PERCENTAGE is the share of items where the field is present and not null.

Get, update, or delete an alert

GET/v2/actors/{actorId}/alerts/{alertId}
PUT/v2/actors/{actorId}/alerts/{alertId}
DELETE/v2/actors/{actorId}/alerts/{alertId}

GET and PUT return { "data": <alert> }. PUT is partial: only fields you send change. DELETE returns 204 with an empty body.

.bash
curl -X PUT "https://api.scrape.ly/v2/actors/{actorId}/alerts/{alertId}" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

curl -X DELETE "https://api.scrape.ly/v2/actors/{actorId}/alerts/{alertId}" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Dataset schema

GET/v2/actors/{actorId}/dataset-schema

Output fields from the build you run (the owner's default build, or the User Build for everyone else), useful for picking a datasetField. The response is { "fields": [{ "name", "type", "format", "title", "description" }] } with no data wrapper, or { "fields": [] } when the build has no dataset schema.

.bash
curl "https://api.scrape.ly/v2/actors/{actorId}/dataset-schema" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
GET/v2/actors/{actorId}/dataset-schema

Bookmarks

Bookmark Actors for quick access.

POST/v2/actors/{actorId}/bookmark
DELETE/v2/actors/{actorId}/bookmark
GET/v2/actors/{actorId}/bookmark
GET/v2/users/me/bookmarks

{actorId} is an Actor ID or a username~name slug; both address the same bookmark. Bookmarks are per user, and adding or removing one twice is harmless. You can have up to 500 bookmarks.

GET /v2/actors/{actorId}/bookmark checks whether you bookmarked that Actor: { "data": { "bookmarked": true, "count": null } }. Bookmark counts are not public: count is the Actor's total only when you own it, and null otherwise.

GET /v2/users/me/bookmarks lists your bookmarked Actors, newest first, one page at a time:

ParameterDescription
offsetNumber of bookmarks to skip. Default 0.
limitPage size, 1 to 200. Default 50.
searchOptional. Matches the Actor's title, name or username, ignoring case; every word must match. Up to 200 characters.

The response is { "data": { "total": 120, "offset": 0, "limit": 50, "count": 50, "items": [...] } }. total counts all your bookmarks that match search (or all of them without one), so you can page through them with offset. Each item has id, name, username, title, description, isPublic, pictureUrl and bookmarkedAt. Actors that were made private by their owner or deleted drop out of the list.

.bash
curl -X POST "https://api.scrape.ly/v2/actors/{actorId}/bookmark" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

POST returns { "data": { "success": true, "bookmarked": true, "count": null } } (count as for GET), 404 not-found if the Actor doesn't exist or is another user's private Actor, or 403 limit-reached if you already have 500 bookmarks (remove one to add another; bookmarking an Actor you already bookmarked still succeeds). DELETE returns { "data": { "success": true, "bookmarked": false, "count": null } }.

Actor templates

Starter templates for new Actors: the same catalog the dashboard's Actor creation wizard and scrapely create --template use. The template values in the examples below are illustrative; read the live catalog for real ones.

List templates

GET/v2/actor-templates

No authentication required.

curl https://api.scrape.ly/v2/actor-templates

language is javascript, typescript, or python. name always equals id. You can also refer to a template by any of its aliases.

GET/v2/actor-templates

Get a template

GET/v2/actor-templates/{templateId}

No authentication required. Returns the template plus the contents of its entry-point file and README for previews (null when missing).

.json
{
  "data": {
    "template": { "id": "js-crawlee-cheerio", "name": "js-crawlee-cheerio", "displayName": "Crawlee + Cheerio" },
    "files": {
      "main": "import { Actor } from ...",
      "readme": "# Crawlee + Cheerio ..."
    }
  }
}
GET/v2/actor-templates/js-crawlee-cheerio

Create an Actor from a template

POST/v2/actors/from-template

Creates an Actor hosted on Scrape.ly with the template's files as its source (version 0.0.1, build tag latest). It doesn't start a build.

Body fieldTypeRequiredDescription
templateIdstringYesTemplate ID or alias.
namestringYesActor name, max 40 characters.
titlestringNoDefaults to the template's displayName.
descriptionstringNoMax 500 characters. Defaults to the template's description.
.bash
curl -X POST https://api.scrape.ly/v2/actors/from-template \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "js-crawlee-cheerio", "name": "my-scraper" }'

Returns 201 with { "data": { "actor": { ... }, "template": { "id", "displayName" } } }. Your Actor-count limit applies.

Create a GitHub repository from a template

POST/v2/actor-templates/{templateId}/git-repo

Requires a connected GitHub integration. Scrape.ly creates a private repository under your GitHub user account (not an organization), pushes the template files, creates an Actor whose source is that repository, and starts the first build.

Body fieldTypeRequiredDescription
repoNamestringYes1–100 characters: letters, digits, ., -, _.
actorNamestringNoLowercase letters, digits, and -, max 40 characters. Defaults to repoName. If taken, a 6-digit suffix is added.
title / descriptionstringNoDefault to the template's values.
autoBuildbooleanNoDefault true: register a GitHub push webhook so every push rebuilds the Actor.

201 response:

.json
{
  "data": {
    "actorId": "actor-uuid",
    "actorName": "my-scraper",
    "gitVersionAttached": true,
    "webhookRegistered": true,
    "webhookUrl": "https://api.scrape.ly/v2/actors/actor-uuid/builds?token=...",
    "buildStarted": true,
    "repo": { "fullName": "jane/my-scraper", "branch": "main" }
  }
}

If the repository can't be created, the Actor is deleted again and nothing is left behind. Webhook registration and the first build are best effort; check webhookRegistered and buildStarted.

Template errors

StatusTypeMeaning
400invalid-inputMissing or invalid body field
400github-not-connectedConnect GitHub first
400profanity-detectedName, title, or description contains blocked words
404template-not-foundUnknown template ID
409name-already-existsActor name taken and no free alternative found
502template-catalog-unavailable / template-fetch-failedTemplate source temporarily unavailable

Support form

POST/v2/public/support

Sends a message to Scrape.ly support. Authentication is optional: with a valid API key, your user ID, account email, and username are attached, and your account email is used if you leave email empty.

Body fieldTypeRequiredDescription
messagestringYes10–5,000 characters.
emailstringYes, unless authenticatedReply-to address.
kindstringNosupport (default) or contact.
topicstringNoaccount, actors, api, store, bug, billing, partnership, general, or other. Unknown values become other (support) or general (contact).
namestringNoMax 120 characters.
subjectstringNoMax 200 characters.
curl -X POST https://api.scrape.ly/v2/public/support \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "topic": "api",
    "subject": "Question about datasets",
    "message": "How do I export a dataset as CSV?"
  }'

Rate limits: 5 requests per hour per IP address, 10 per day per account when authenticated, and 5 per hour per email address. Errors: 400 invalid-input (bad kind, invalid email, or message under 10 characters), 429 rate-limit-exceeded, and 502 email-failed (email support@scrape.ly directly instead).

Integrations

Connect Slack and GitHub to your account. In the dashboard these live in Settings → Connections.

List integrations

GET/v2/integrations
curl "https://api.scrape.ly/v2/integrations" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Each value includes connected. When connected, credential (provider metadata) and integration (integrationType, enabled, config, timestamps) are also present. For GitHub, scopes, missingScopes, and reconnectRequired tell you whether the connection needs to be renewed to grant newly required scopes.

GET/v2/integrations

Disconnect

DELETE/v2/integrations/{type}

type is one of slack, github, gmail, google_drive, or airtable. Returns 204. Invalid types return 400 invalid-integration.

.bash
curl -X DELETE "https://api.scrape.ly/v2/integrations/slack" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

OAuth

These routes start a browser OAuth flow and redirect back to the dashboard, which opens Settings → Connections. Open them in a browser while signed in; they are not JSON APIs.

EndpointDescription
GET /v2/integrations/oauth/slackRedirect to Slack authorization.
GET /v2/integrations/oauth/slack/callbackSlack return URL. Stores credentials and redirects to the dashboard.
GET /v2/integrations/githubRedirect to GitHub authorization.
GET /v2/integrations/github/callbackGitHub return URL. Stores credentials and redirects to the dashboard.

Callbacks return 400 invalid-request for a missing code or state and 400 invalid-state for an expired OAuth state.

GitHub repositories

GET/v2/integrations/github/repos

Lists repositories for the connected GitHub account (most recently updated first when not searching). Requires a GitHub integration (400 not-connected otherwise).

Query paramTypeDefaultDescription
pagenumber1Page number.
per_pagenumber30Page size.
searchstring—Search your repositories instead of browsing.
curl "https://api.scrape.ly/v2/integrations/github/repos?page=1&per_page=30&search=scraper" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Errors

StatusTypeMeaning
400invalid-inputMissing alert name or trigger type, or invalid template/support input
400not-connected / github-not-connectedGitHub is not connected
400invalid-integrationUnknown integration type
401token-not-validInvalid or revoked token
403forbiddenActor is private and you don't own it
404actor-not-found / alert-not-found / template-not-foundUnknown Actor, alert, or template
429rate-limit-exceededToo many requests