On this page

    Build features

    Capture Pages on a Schedule

    Keep a dated visual record of your pages or a competitor's: full-page captures every day from cron or GitHub Actions, with a credit budget.

    Time
    20 minutes
    Plan
    Free
    You need
    • An API key in RS_API_KEY
    • A server with cron, or a GitHub repository

    What you will have at the end

    One dated, full-page capture per page per run: a record you can compare later.

    Scheduled captures give you a dated picture of a page: your own pages after each release, a competitor's pricing page, a partner's listing, or a page you must keep for compliance. You will write one short script and run it every day.

    List the pages and count the credits

    Each capture uses one credit. Multiply before you start:

    Pages Runs per day Credits per month Plan that covers it
    5 1 150 Free (150 a month)
    20 1 600 Starter (2,500)
    40 2 2,400 Starter (2,500)
    100 4 12,000 Growth (12,000)

    Put the URLs in a file, one per line:

    # pages.txt
    https://renderscreenshot.com/pricing
    https://renderscreenshot.com/changelog
    https://example.com
    

    Write the capture script

    The script asks for the whole page (full_page preset), closes cookie banners, and saves each image as captures/<date>/<host>-<path>.png. Failed pages do not stop the run.

    Bash and curl

    #!/usr/bin/env bash
    # capture.sh: one full-page capture per URL in pages.txt
    set -uo pipefail
    day=$(date -u +%F)
    mkdir -p "captures/$day"
    
    grep -v '^#' pages.txt | while read -r url; do
      [ -z "$url" ] && continue
      name=$(echo "$url" | sed -E 's#^https?://##; s#[^a-zA-Z0-9]+#-#g; s#-$##')
      status=$(curl -sS -X POST https://api.renderscreenshot.com/v1/screenshot \
        -H "Authorization: Bearer $RS_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{\"url\": \"$url\", \"preset\": \"full_page\", \"block\": {\"cookie_banners\": true}}" \
        --max-time 120 -o "captures/$day/$name.png" -w '%{http_code}')
      echo "$status $url"
      [ "$status" = "200" ] || rm -f "captures/$day/$name.png"
    done
    

    Node.js

    // capture.mjs: node capture.mjs
    import { mkdir, readFile, writeFile } from 'node:fs/promises';
    import { Client, TakeOptions } from 'renderscreenshot';
    
    const client = new Client(process.env.RS_API_KEY, { timeout: 120_000 });
    const day = new Date().toISOString().slice(0, 10);
    await mkdir(`captures/${day}`, { recursive: true });
    
    const urls = (await readFile('pages.txt', 'utf8'))
      .split('\n').map((line) => line.trim()).filter((line) => line && !line.startsWith('#'));
    
    for (const url of urls) {
      const name = url.replace(/^https?:\/\//, '').replace(/[^a-z0-9]+/gi, '-').replace(/-$/, '');
      try {
        const image = await client.take(TakeOptions.url(url).preset('full_page').blockCookieBanners());
        await writeFile(`captures/${day}/${name}.png`, image);
        console.log('ok', url);
      } catch (error) {
        console.error('failed', url, error.code ?? error.message);
      }
    }
    

    The full_page preset scrolls through the page first, so images that load on scroll appear in the capture.

    A full_page capture is 1280 pixels wide and as tall as the page, up to 16,000 pixels.

    Run it every day

    cron

    # crontab -e: every day at 06:00 UTC
    0 6 * * * cd /srv/captures && RS_API_KEY=rs_live_... ./capture.sh >> capture.log 2>&1
    

    GitHub Actions

    # .github/workflows/captures.yml
    name: Daily captures
    
    on:
      schedule:
        - cron: '0 6 * * *'
      workflow_dispatch:
    
    jobs:
      capture:
        runs-on: ubuntu-latest
        timeout-minutes: 20
        steps:
          - uses: actions/checkout@v4
          - name: Capture pages
            env:
              RS_API_KEY: ${{ secrets.RS_API_KEY }}
            run: bash capture.sh
          - uses: actions/upload-artifact@v4
            with:
              name: captures-${{ github.run_id }}
              path: captures/
              retention-days: 90
    

    Add RS_API_KEY under Settings → Secrets and variables → Actions in the repository. GitHub keeps the files for 90 days. To keep them longer, save screenshots to your bucket with a dated path such as {year}/{month}/{day}/{domain}-{hash}.{ext}.

    Check the runs

    Usage in the dashboard shows the requests per day. A daily job is a flat line. A gap means a run did not happen.

    Logs shows each capture. A failed capture shows the reason and costs no credits. The most common reason for a scheduled job is a timeout on a slow page; fix blank or incomplete screenshots shows the fix.

    Next steps

    Try RenderScreenshot free

    150 free credits every month, no credit card required.