---
title: "Config, CI/CD & troubleshooting · Scrape.ly Docs"
description: "Help, upgrades, config files, environment variables, CI/CD, and common fixes."
url: https://scrape.ly/docs/cli-config
markdown: https://scrape.ly/docs/cli-config.md
---

# Config, CI/CD & troubleshooting

> Help, upgrades, config files, environment variables, CI/CD, and common fixes.

This page collects everything that configures the CLI: the help and upgrade commands, the files it reads and writes, and the environment variables it honours. It also shows how to run the CLI in CI pipelines and how to fix common errors.

## Help

```bash
scrapely help
scrapely help push
scrapely help "actors ls"
scrapely push --help
```

`scrapely help` prints an overview of the command groups. With a command, including a nested one in quotes, it prints that command's options. `--help` after any command does the same.

| Option | Description |
| --- | --- |
| `--skill` | Print the CLI's agent skill: instructions for driving the CLI from an AI coding assistant |

## Upgrade the CLI

```bash
scrapely upgrade
scrapely upgrade --version 0.2.0
```

`upgrade` compares the installed version with the latest one on npm (`npm view scrapely-cli version`) and runs `npm install -g scrapely-cli@latest` if yours is older.

| Option | Description |
| --- | --- |
| `-f, --force` | Reinstall even when you're on the latest version |
| `--version <version>` | Install this version, for example `1.2.3`, `v1.2.3-beta.1`, or `latest` |

If npm needs elevated permissions for global installs on your machine, `upgrade` fails with a permissions error. Run `npm install -g scrapely-cli@latest` yourself in that case.

## Files

### In your home folder

The CLI keeps its own state in `~/.scrapely/`. Both files are written with mode `0600`.

| File | Contents |
| --- | --- |
| `credentials.json` | Token, API URL, and cached user details, written by `login` and emptied by `logout` |
| `secrets.json` | Local secrets for `scrapely run`, managed with `scrapely secrets` |

### In your project

The Actor config is the first of these files that exists in the project folder:

1. `.actor/actor.json`
2. `.actor/scrapely.json`
3. `scrapely.json`
4. `actor.json`

If the config is in `.actor/` and the folder also has a root `scrapely.json`, the root file's fields override those in `.actor/`. Paths in the config, such as `input` or `dockerfile`, are relative to the file that contains them. `package.json` provides `name`, `version`, and `actorId` when the config doesn't. The fields are described in [Projects & running](https://scrape.ly/docs/cli-projects.md#project-configuration).

Other project files the CLI reads:

| File | Read by |
| --- | --- |
| `.gitignore`, `.actorignore` | `push`: both lists of patterns are excluded from the upload |
| `storage/key_value_stores/default/INPUT.json` | `run`, `call`, `actors call`, `actors start`, and `task run` when you don't pass input |
| `.actor/input_schema.json` | `run`, for defaults and required fields, when the config has no `input` |

## Environment variables

### For CLI commands

| Variable | Purpose |
| --- | --- |
| `SCRAPELY_TOKEN` | API token, used when no token is saved |
| `SCRAPELY_API_BASE_URL` | API URL. Wins over everything else. |
| `SCRAPELY_API_URL` | API URL, when `SCRAPELY_API_BASE_URL` isn't set |
| `SCRAPELY_WEB_URL` | Dashboard URL for printed links and `push --open` |

A saved token wins over `SCRAPELY_TOKEN`, but the API URL variables win over the saved API URL. Without any API URL, the CLI uses its built-in default, which is not the production API. Set `SCRAPELY_API_URL=https://api.scrape.ly` and `SCRAPELY_WEB_URL=https://my.scrape.ly`. See [Authentication](https://scrape.ly/docs/cli-auth.md#credentials-and-precedence).

### For runtime commands

The `scrapely actor` commands also read `ACTOR_TOKEN`, `APIFY_TOKEN`, and `APIFY_API_BASE_URL`, and the run and storage IDs the platform sets in each container. The other commands ignore these. See [Actor runtime](https://scrape.ly/docs/cli-actor-runtime.md#environment).

### Set for your code by `scrapely run`

`run` sets `ACTOR_INPUT` (the input as base64-encoded JSON), `ACTOR_INPUT_KEY=INPUT`, and the variables from the config's `environmentVariables`.

## CI/CD

In a pipeline, authenticate with an API key in `SCRAPELY_TOKEN`. Don't run `scrapely login`: without `--token` it waits for input. Browser-login tokens expire, so don't copy one from your machine into CI.

### GitHub Actions

```yaml
name: Deploy Actor
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Install CLI
        run: npm install -g scrapely-cli

      - name: Check schemas
        run: scrapely validate-schema

      - name: Deploy
        env:
          SCRAPELY_API_URL: https://api.scrape.ly
          SCRAPELY_TOKEN: ${{ secrets.SCRAPELY_TOKEN }}
        run: scrapely push --force --wait-for-finish 900
```

### GitLab CI

```yaml
deploy:
  stage: deploy
  image: node:22
  variables:
    SCRAPELY_API_URL: https://api.scrape.ly
  script:
    - npm install -g scrapely-cli
    - scrapely validate-schema
    - scrapely push --force --wait-for-finish 900
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
```

Define `SCRAPELY_TOKEN` as a masked CI/CD variable in the project settings.

The first `push` writes the new `actorId` into the config file. Commit that change, or every pipeline run on a fresh checkout creates another Actor.

In CI, `push` can't ask before overwriting an Actor that changed on the platform after your files did, so it fails instead. Pass `--force` when the repository is the source of truth, as above.

### Rebuild on Git push without a pipeline

If the Actor's source is a GitHub repository, the platform can rebuild it on every push to the linked branch without running the CLI. With the GitHub integration connected, linking the repository registers the webhook for you, and `scrapely create --source github --auto-build on` does it for new projects. To add or repair the webhook on an existing Actor, run `scrapely api POST /v2/actors/<actorId>/ci/webhook -d '{}'`. For other Git hosts, get the build URL with `scrapely api GET /v2/actors/<actorId>/ci/webhook-url` and add it as a webhook there. See [Integrations](https://scrape.ly/docs/integrations.md).

### Scripting tips

- Keep the token in your CI secret store. Never commit it.
- Pass `-y` to delete commands so nothing waits for confirmation.
- Use `--json` and `jq` instead of parsing the formatted output, which can change.
- Let `push` wait for the build, so a failed build fails the job. With `-w <seconds>`, a build still running at the deadline exits with code 0.
- Check exit codes: `call`, `runs wait`, and `builds wait` exit with code 1 unless the run or build `SUCCEEDED`.

Start a run, wait for it, and export the results:

```bash
RUN_ID=$(scrapely actors start janedoe~my-actor -i '{"query":"coffee"}' --json | jq -r '.data.id')
scrapely runs wait "$RUN_ID" --timeout 900
DATASET_ID=$(scrapely runs info "$RUN_ID" --json | jq -r '.data.defaultDatasetId')
scrapely datasets get-items "$DATASET_ID" --format csv > results.csv
```

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| `scrapely: command not found` | npm's global bin folder is not on `PATH` | Add it, or use `npx scrapely-cli` |
| `You are not logged in. Call "scrapely login" first.` | No saved token and no `SCRAPELY_TOKEN` | Run `scrapely login`, or set `SCRAPELY_TOKEN` |
| 401 errors after working earlier | The browser-login token expired | Run `scrapely login` again, or use an API key |
| `Using default API at …` on login, or commands reach the wrong server | No API URL set | Set `SCRAPELY_API_URL=https://api.scrape.ly`. Check with `scrapely info`. |
| `SCRAPELY_TOKEN` seems ignored | A saved token wins over the variable | Run `scrapely logout` |
| Dashboard links point at the wrong host | `SCRAPELY_WEB_URL` isn't set | Set `SCRAPELY_WEB_URL=https://my.scrape.ly` |
| `Actor ID is required` | No ID given, and no `actorId` in the local config | Pass the ID, or run the command in the project folder after the first `push` |
| `Error: Missing secrets used by environment variables` | An `@name` in the config isn't in your local secrets | `scrapely secrets add <name>`, or pass `--allow-missing-secrets` |
| `push` stops because the Actor on the platform is newer | Someone changed the Actor after your files | Check what changed in the dashboard, then `scrapely push --force` |
| Build fails | Dockerfile error, or a needed file wasn't uploaded | Read `scrapely builds log <buildId>`. Check `.gitignore` and `.actorignore`. |
| `No successful build found` when starting a run | The Actor has never built successfully | Fix the build and push again |
| `scrapely run` fails on the SDK import | The SDK isn't installed locally | Run on the platform with `scrapely call`. See [Projects & running](https://scrape.ly/docs/cli-projects.md#run-locally). |
| Run fails | Error in the code, or invalid input | Read `scrapely runs log <runId>`. Compare the input with `scrapely actors info <actorId> --input`. |
| `429` responses | Rate limit | Wait and retry. See [API overview](https://scrape.ly/docs/api-overview.md). |

### Getting more detail

When a command fails, the CLI prints the API's error message under `Details:`. To see the raw response, repeat the request with `scrapely api`:

```bash
scrapely api GET /v2/users/me
scrapely api GET /v2/actors/janedoe~my-actor
```

## What's next

- [Authentication](https://scrape.ly/docs/cli-auth.md): tokens and precedence.
- [Secrets, webhooks & API](https://scrape.ly/docs/cli-webhooks-secrets.md): the `api` command in full.
- [API overview](https://scrape.ly/docs/api-overview.md): status codes, errors, and rate limits.

---

- Previous: [Secrets, webhooks & API](https://scrape.ly/docs/cli-webhooks-secrets.md)
- Next: [Publish & monetize](https://scrape.ly/docs/publishing.md)
- All docs: [Docs index](https://scrape.ly/docs.md), [llms.txt](https://scrape.ly/llms.txt)
