ScreenshotNeo

BlogHow-to

How to Upload Screenshots to Argos CI from a Self-Hosted Runner

Generate screenshots on your self-hosted runner, then upload them to Argos CI with its CLI or Node.js SDK. Configure authentication and CI metadata for reliable build association.

By the ScreenshotNeo team4 October 20268 min read

Direct answer: Generate screenshot files on your self-hosted runner, then upload the directory with the Argos CLI: argos upload ./screenshots. Set ARGOS_TOKEN for authentication unless your CI setup supports another documented route. The CLI handles files produced by different frameworks; if upload needs to happen inside a Node.js process, use the Argos SDK with a root directory and file globs.

Uploading does not capture screenshots for you. Your test or capture step must first write supported image files to the runner’s filesystem. The examples below separate capture and upload so the same upload step can work with Playwright, Cypress, mobile test frameworks, or another tool that saves screenshots to disk.

1. Generate screenshots and confirm their location

Choose the capture method your project already uses. The important contract is that the capture step writes image files to a known directory before upload begins. For example, if the output is ./screenshots, the upload command must target that exact path.

npm run test:visual
find ./screenshots -type f

The find command is a useful runner-side check: it confirms the directory exists and shows the files available to upload. Change the path in the upload command if your test framework writes somewhere else.

2. Upload with the Argos CLI

Run the CLI after screenshot generation. Argos documents the directory upload pattern as argos upload ./screenshots. In an npm-based job, the invocation can be made through npx:

npx @argos-ci/cli upload ./screenshots

Install and pin the CLI in the way that fits your runner image and dependency policy. The command above shows the package invocation; package installation details can vary by runner and project. Check the current Argos CLI package documentation when choosing a pinned version or installation method.

Generic runner sequence

  1. Check out the source code and install the project dependencies.
  2. Run the browser or test framework step that creates screenshots.
  3. Confirm the output directory and files exist.
  4. Run argos upload against that directory.
  5. Provide authentication through the CI secret mechanism.
  6. Check the Argos build to confirm it is associated with the intended commit or pull request.

Example GitHub Actions job

This is an implementation outline. The workflow syntax for npm ci, the test script, output path, and secret interpolation are project choices; adapt them to your repository.

name: Visual screenshots

on:
  pull_request:
  push:

jobs:
  screenshots:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: npm ci
      - name: Capture screenshots
        run: npm run test:visual
      - name: Upload screenshots to Argos
        run: npx @argos-ci/cli upload ./screenshots
        env:
          ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}

Create and protect the ARGOS_TOKEN secret according to your repository’s secret management practices. Do not print it in job logs or pass it as a command-line argument that may be recorded in process output.

3. Authenticate the runner

For a generic self-hosted runner, set ARGOS_TOKEN in the job environment using the CI provider’s secret mechanism. The Argos Node.js SDK also uses this environment variable as its default token source. Keep the value scoped to the upload job where practical and avoid logging the environment.

GitHub Actions OIDC

Argos documents GitHub Actions OIDC as an alternative to storing a reusable Argos token. To use it, enable OIDC in the Argos project settings and grant the workflow id-token: write. The corresponding job can omit ARGOS_TOKEN:

permissions:
  contents: read
  id-token: write

jobs:
  screenshots:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test:visual
      - run: npx @argos-ci/cli upload ./screenshots

OIDC and the documented tokenless fallback behavior are specific to GitHub Actions. Argos describes a fallback for runs where GitHub does not issue an OIDC token, including certain fork pull request and public repository situations, after verifying the workflow run with GitHub. Do not assume the same authentication flow is available on another self-hosted CI provider; use the provider-specific and Argos instructions for that environment.

4. Use the Node.js SDK when upload belongs in a script

The CLI is usually the simpler choice when a framework already writes screenshot files and upload is a separate pipeline step. Use the SDK when upload belongs inside an existing Node.js process, or when the root directory and file patterns need to be set programmatically.

import { upload } from "@argos-ci/core";

await upload({
  root: "./artifacts",
  files: ["screenshots/**/*.png", "screenshots/**/*.jpg"],
  // token defaults to ARGOS_TOKEN when omitted
});

Run the script after capture and set ARGOS_TOKEN in the runner environment. Set root to the directory against which your file patterns should be resolved, then adjust files to match the screenshot formats and layout your capture step actually produces. The SDK reference documents the token’s default as the ARGOS_TOKEN environment variable.

5. Preserve commit, branch, and pull request association

The Argos CLI reads commit, branch, and pull request information from CI environment variables. A successful image upload can still be hard to use if the build is associated with the wrong change or lacks expected metadata.

  • Run the upload in the same CI job or context that has the checkout and change metadata.
  • Check that your CI provider exposes the expected commit, branch, and pull request values.
  • When a build is missing or associated unexpectedly, inspect the runner’s CI environment and provider integration configuration.
  • Do not copy GitHub-specific environment assumptions into another CI system without checking its metadata conventions.

6. Choose CLI, SDK, or a framework integration

Approach Use it when What to check
CLI directory upload A capture tool writes files and upload can be a separate command. Target path, authentication, and CI metadata.
Node.js SDK Upload belongs inside a Node script or requires programmatic root and glob configuration. Root directory, file globs, and ARGOS_TOKEN.
Playwright reporter or helper Your capture workflow uses Playwright and an integrated reporter or argosScreenshot helper fits the test design. Follow the framework integration setup and confirm its upload behavior in your CI environment.

Argos documents both the general CLI route and a Playwright integration. The CLI is useful when screenshots come from a different framework or when you intentionally keep capture and upload separate.

7. Make screenshot output reproducible

Screenshot comparisons depend on how a page is rendered. Differences in operating system, browser, fonts, dependencies, or capture setup can create visual changes unrelated to the application. For repeatable comparisons, keep the runner image and browser setup stable and install the same dependencies consistently.

  • Use a stable self-hosted runner image and browser version where possible.
  • Keep fonts and system packages consistent between runs.
  • Use a lockfile-based dependency install, such as npm ci for an npm project.
  • Make sure the capture step waits for the page state your tests intend to compare.
  • Keep the screenshots from one run together in a predictable output directory.

8. Troubleshooting

Symptom Likely cause Fix
No screenshots appear in the Argos build The capture step did not run, wrote files elsewhere, or the CLI path does not match. Inspect the runner output directory after capture, then point the CLI at the directory that contains the files.
Authentication fails ARGOS_TOKEN is missing or unavailable to the upload step, or the selected CI auth setup is incomplete. Check the protected secret mapping and job environment. For GitHub OIDC, verify the Argos project setting and id-token: write permission.
Build is not tied to the expected pull request or commit The CLI cannot read the expected CI metadata, or upload runs outside the expected CI context. Check commit, branch, and pull request metadata exposed to the job; keep upload in the CI context that owns the checkout.
Unexpected visual diffs between identical changes Rendering conditions vary across runner images, operating systems, browsers, or fonts. Stabilize the runner and browser environment and keep dependencies and fonts consistent.
Some files are absent from an SDK upload The configured root or files globs do not match the generated directory structure. List the generated files on the runner and adjust the root and patterns to include their actual paths and extensions.
Unsure whether to use a reporter or the CLI The upload path has not been matched to the framework workflow. Use the framework integration when its reporter/helper suits the test run; use CLI upload for screenshots already written to disk by varied frameworks.

9. Performance, reliability, and cost considerations

The upload flow adds work after capture, so avoid capturing the same pages twice just to satisfy upload. Generate the artifacts once, then upload the resulting directory. Keep the output directory focused on screenshots intended for comparison; this makes path mistakes easier to diagnose and avoids sending unrelated files.

Reliability depends on both halves of the pipeline: the capture step must finish with usable files, and the upload step must run with authentication and CI metadata. Preserve enough job output to diagnose missing artifacts or incorrect paths, but never print secrets. A stable runner environment reduces noise in visual comparisons.

The research dossier does not specify Argos pricing, upload limits, or performance benchmarks, so this guide makes no cost or speed claims. Check current Argos plan and product documentation for those details when estimating pipeline cost.

Or skip the browser setup

If your task is to obtain a page screenshot rather than compare screenshots generated by your own test suite, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. A single request returns a PNG, JPEG, WebP, or PDF. It does not replace Argos’s visual comparison workflow for application-generated test screenshots; it is an option when you need to capture a website directly.

For example, this cURL request saves a screenshot of Stripe:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Equivalent Python request:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Equivalent Node.js request:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write("shot.webp", new Uint8Array(await res.arrayBuffer()));

See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; these steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed, and response headers identify the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo and get 1,000 screenshots a month free with no card.

FAQ

Does the Argos upload command take screenshots?

No. A capture or test step must first create the screenshot files. The CLI uploads files from the directory you specify.

Can I upload screenshots made by Cypress or a mobile test framework?

The CLI is documented as a framework-independent file upload route, provided your capture workflow writes image files that Argos accepts.

Can a self-hosted GitHub Actions runner use OIDC?

Argos documents GitHub Actions OIDC setup using the project setting and workflow id-token: write permission. Follow the current Argos instructions for the project and workflow configuration.

What should I use if screenshots already exist before the job starts?

Make those files available in the runner workspace, confirm their directory, then use the CLI upload step or the SDK with matching root and file patterns.