Menu
Sign up

Schedule website screenshots: daily captures with GitHub Actions, Zapier or n8n

Take a screenshot of a website every day or hour without a server: a GitHub Actions cron job, a Zapier or n8n schedule, and how caching and storage work.

Published November 8, 2026 · 5 min read

A screenshot of a page every morning gives you a record nobody else keeps: how your home page looked on launch day, when a competitor changed its pricing, whether the status dashboard was green at 9:00, what an ad landing page showed during a campaign. Taking it by hand stops after the third day. This page shows three ways to take it automatically without running a browser yourself — a GitHub Actions workflow, a Zapier or n8n schedule, or plain cron — with our screenshot API doing the capture, and the details that decide whether it works: caching, storage and timing.

The capture itself

Every scheduler below makes the same request:

curl -s -X POST "https://shareglint.com/v1/screenshots?wait=true" \
  -H "Authorization: Bearer $SCREENSHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/pricing", "full_page": true, "lazy_load": true,
        "block_cookie_banners": true, "format": "jpeg" }'

The JSON response has a url with the finished image. ?wait=true holds the connection until the screenshot is ready; without it, the call returns at once with an id to poll (GET /v1/screenshots/{id}), or add a webhook_url and we call you with screenshot.completed or screenshot.failed. A viewport screenshot uses 1 render of your monthly quota, a full page 2.

Two parameters matter most for a schedule: full_page with lazy_load, so images further down the page are loaded before the capture, and block_cookie_banners, so a consent dialog does not cover the page in every image of your archive.

Option 1: GitHub Actions (no server of your own)

# .github/workflows/screenshots.yml
name: Daily screenshots
on:
  schedule:
    - cron: "17 6 * * *"        # 06:17 UTC every day
  workflow_dispatch:            # a "Run workflow" button for testing

jobs:
  capture:
    runs-on: ubuntu-latest
    steps:
      - name: Capture the pricing page
        env:
          SCREENSHOT_API_KEY: ${{ secrets.SCREENSHOT_API_KEY }}
        run: |
          page="https://example.com/pricing?t=$(date -u +%F)"   # a new URL each day: never a cached image
          url=$(curl -sf -X POST "https://shareglint.com/v1/screenshots?wait=true" \
            -H "Authorization: Bearer $SCREENSHOT_API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$page\",\"full_page\":true,\"lazy_load\":true,\"block_cookie_banners\":true,\"format\":\"jpeg\"}" \
            | jq -r .url)
          mkdir -p shots && curl -sf "$url" -o "shots/pricing-$(date -u +%F).jpg"
      - uses: actions/upload-artifact@v7
        with:
          name: screenshots
          path: shots/

Store the API key as a repository secret, never in the file. What GitHub's schedule documentation says about the timing, as of 2026-11-08:

  • Schedules use POSIX cron syntax and run in UTC by default; a timezone: key with an IANA name such as "Europe/Berlin" sets another.
  • The shortest interval is once every 5 minutes.
  • Runs "can be delayed during periods of high loads", and the start of every hour is one of them — which is why the example runs at :17, not :00.
  • In a public repository, scheduled workflows are disabled after 60 days without repository activity.

Artifacts made with actions/upload-artifact expire after a retention period too; for a permanent archive, commit the images to a branch, or upload them to S3 or another store in an extra step.

Option 2: Zapier, Make or n8n

All three have a schedule trigger and an HTTP step, so the flow is the same:

  1. Schedule — every day at a time, every hour, or every Monday.
  2. HTTP request — the POST above, with the API key in the header.
  3. Save the file — the image URL into Google Drive, Dropbox, an Airtable attachment field or a Slack message.

Our recipes show the HTTP step for each tool: Zapier, Make and n8n. We have no app inside these tools; the HTTP step is the integration. A no-code schedule suits a handful of pages; for dozens, a script is cheaper to run and easier to change.

Option 3: cron on a server you already have

The curl command above, in a shell script, in crontab -e:

17 6 * * * /opt/shots/capture.sh >> /var/log/shots.log 2>&1

Nothing else is needed — no Chrome on the server, no fonts, no memory for a browser.

Caching: when a schedule returns yesterday's picture

The same URL with the same options within 24 hours returns the existing file without a new capture and without using quota. That saves money on retries and repeated requests, and it means:

  • Less often than every 24 hours: usually outside the window, so a fresh capture — but if yesterday's run was delayed and today's is on time, the two can be less than 24 hours apart, and today's run gets yesterday's image.
  • More often, or to be safe: add a query parameter that changes per run, such as ?t=2026-11-08 (or …T14 for hourly), so each run is a new URL and always a new capture. Most sites ignore unknown parameters; check that yours does not show a different page for them.

We checked this on 2026-11-08: a full-page capture of a test URL took about 5 seconds and used 2 renders; sending the identical request again returned the same image id at once and used nothing more.

The API also accepts an Idempotency-Key header: a retried request with the same key and body returns the first response instead of capturing again, which protects you from double captures when a scheduler retries a step.

Storage and naming

Keep your own copy of every image: ours are kept for 365 days on paid plans, an archive is usually meant for longer. Name files by page and UTC date — pricing-2026-11-08.jpg — so they sort in time order, and keep the capture options in the job's code, so next year's images are comparable with this year's. JPEG keeps full-page archives small; PNG is better if you will compare images pixel by pixel.

Knowing when something changed

A schedule gives you images; noticing a change means comparing today's with yesterday's. An image diff such as pixelmatch does that in a few lines, and our visual regression guide measured what makes such comparisons flaky. We do not send change alerts ourselves: the comparison and the notification are your job's last steps. To capture many pages in one run, see bulk website screenshots.

FAQ

How do I take a screenshot of a website every day automatically?

Run a scheduled job that calls a screenshot API and saves the image: a GitHub Actions workflow with a cron schedule, a Zapier or n8n schedule trigger, or cron on any server. Each run sends the page URL and options, receives the image URL, and copies the file to your own storage.

Can GitHub Actions take screenshots on a schedule?

Yes. A workflow with on: schedule: - cron: '0 6 * * *' runs daily; GitHub's docs say the shortest interval is once every 5 minutes, schedules run in UTC unless you set a timezone, and runs can be delayed at busy times such as the start of every hour. In public repositories, scheduled workflows are disabled after 60 days without activity.

Why does my scheduled screenshot return the same image as yesterday?

Our API returns the existing file for the same URL with the same options within 24 hours, without using quota. A daily job can land just inside that window when the previous run was delayed; add a query parameter that changes per run, such as ?t=2026-11-08, so each run is a new capture.

How long are scheduled screenshots kept?

On our side, for your plan's retention period — 365 days on paid plans. For an archive, download each image when the job finishes and store it yourself, in S3, Google Drive, a repository or a database.