How to automate daily website screenshots with Screenshot.rocks
Screenshot.rocks makes mockups from existing screenshots; for daily captures, schedule a separate screenshot workflow with GitHub Actions or use an API.
Screenshot.rocks is described as a mockup editor for screenshots you already have, not as a daily screenshot scheduler. It can place an existing screenshot in a browser or iPhone frame, add a background or annotations, and export the result. To capture a site every day, schedule a separate browser or screenshot API job. [Screenshot.rocks]
This guide sets up a self-hosted daily workflow with shot-scraper and GitHub Actions. The cited documentation describes this general approach—take screenshots in a workflow and write them back to a repository—but does not substantiate a complete current configuration or its scheduling, retention, and failure behavior. Check the current shot-scraper and GitHub Actions documentation before adopting the example below in production. [shot-scraper documentation]
What Screenshot.rocks does, and what it does not document
The available official product description presents Screenshot.rocks as a tool for turning an existing screenshot into a presentation mockup. It says processing happens in the browser and images are not stored on its servers. The reviewed description and repository description do not document recurring capture or scheduling. Do not assume the product itself takes daily screenshots unless its current interface or documentation confirms that capability. [Screenshot.rocks] [Repository description]
There are two separate jobs:
- Capture: load a URL in a browser or screenshot service and save an image.
- Presentation: use an existing image in Screenshot.rocks to frame, annotate, and export a mockup.
A scheduled capture can produce images for later presentation. Confirm in Screenshot.rocks that the image format and import/export flow you need are supported before building a downstream process around it.
Choose a daily capture workflow
For a small set of pages, a scheduled GitHub Actions workflow is a practical starting point: the workflow runs at a chosen UTC time, captures configured URLs, and stores the files in the repository. This keeps the schedule and configuration alongside your code. It also means you must decide how to handle browser dependencies, failures, generated-file commits, and image retention.
Use a hosted screenshot API if you prefer not to maintain a browser runtime or want request-level options such as viewport, output format, waiting behavior, or full-page capture. For pages behind authentication, check the service’s support for cookies or headers and protect credentials as secrets.
Set up daily captures with shot-scraper and GitHub Actions
The workflow below is a starting template, not a verified current recipe: the research source describes this pattern but does not confirm the present shot-scraper command syntax, configuration schema, or action requirements. Verify the current shot-scraper documentation and GitHub Actions documentation, then adjust the install and capture commands to match their current versions.
- Create a repository for the capture job, or use an existing repository with a dedicated output directory.
- Install shot-scraper in the workflow using the currently documented installation command.
- Configure the URLs, output paths, viewport, and any required wait behavior using the current shot-scraper configuration format.
- Run the capture command in the workflow and write generated images into a known directory.
- Commit or otherwise publish the generated files. Configure permissions and retention deliberately.
GitHub Actions cron schedules use UTC. Choose a UTC time that corresponds to your intended local time, and account for daylight-saving changes yourself if the capture must stay at a fixed local wall-clock time. Consult the current GitHub Actions documentation for cron syntax, schedule behavior, permissions, and limits.
# .github/workflows/daily-screenshots.yml
# Template only: confirm shot-scraper install/configuration/CLI syntax
# and the current checkout/setup action versions before use.
name: Daily website screenshots
on:
schedule:
- cron: "17 7 * * *" # 07:17 UTC every day
workflow_dispatch:
permissions:
contents: write
jobs:
capture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install shot-scraper
run: |
python -m pip install --upgrade pip
# Replace with the current documented install command if it changes.
python -m pip install shot-scraper
- name: Capture configured pages
run: |
# Add the current documented configuration and capture command here.
# Example shape only; verify exact CLI options in shot-scraper docs.
shot-scraper --help
- name: Commit generated screenshots
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add screenshots/
git diff --cached --quiet || git commit -m "Update daily screenshots"
git push
The capture step intentionally stops at --help: the available research does not verify a particular shot-scraper configuration or command. Replace it with the current documented invocation and add the corresponding config file before relying on this workflow. Also verify that the selected runner supports the browser dependencies the tool needs.
Decide how images are stored
- Commit images to the repository: straightforward history and review, but the repository grows with every run. Use an explicit retention policy or a separate artifact store if the image history becomes large.
- Workflow artifacts: useful for temporary inspection, subject to the platform’s current artifact retention and limits. Verify those settings in the platform documentation.
- Object storage: keeps binary history outside source control, but requires credentials, lifecycle rules, and access controls.
A daily job creates 365 captures per URL per year, before accounting for retries or multiple viewport sizes. Estimate storage using the actual average file size from your pages, then set retention based on how much history is useful.
Configuration decisions that affect useful captures
URL and page state
Use stable, canonical URLs and decide whether query parameters matter. A page with rotating content, personalized recommendations, or a changing timestamp can produce noisy image differences. For authenticated pages, use a dedicated least-privilege account and pass secrets through the workflow’s secret store; do not commit cookies, tokens, or passwords into the repository.
Viewport and page length
Keep viewport dimensions consistent between runs if you want meaningful visual comparisons. Decide whether you need the initial viewport or a full-page image. Full-page captures can be much larger and may trigger lazy-loaded content; verify how the chosen capture tool scrolls and waits before assuming all below-the-fold content is included.
Wait behavior
Pages may render after the initial HTML response because of JavaScript, fonts, images, or API calls. Use a documented selector wait or delay when a specific element signals readiness. A fixed delay is simple but can waste time on fast pages and still fail on slow ones. Network-idle waits can also be unreliable on pages with long-lived requests. Choose a readiness condition tied to the content you need when the tool supports it.
Output naming
Include the page identifier and date in each filename, for example screenshots/home/2026-10-04.png. Use a stable timezone for date naming and avoid overwriting yesterday’s image unless the purpose is to keep only the latest capture.
Run captures with an API instead
A screenshot API removes the need to install and maintain a browser in the scheduled job. The same daily scheduler can call the API, save the response, and apply your chosen storage policy. Keep the API key in a repository secret, pass it at runtime, and avoid printing request URLs containing credentials in logs.
For any API, check its current documentation for accepted parameters, response content types, timeouts, error responses, authentication, and billing rules. A successful HTTP request does not necessarily mean the page rendered correctly; inspect the returned status and image output according to that API’s documented behavior.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its one-call API can return an image or PDF; see the ScreenshotNeo API documentation for options you can add to a scheduled request.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
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 import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
Adapt the target URL and keep the key in your scheduler’s secret store. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for free and get 1,000 screenshots a month with no card.
Reliability, performance, and cost
- Schedule reliability: a scheduled workflow can be delayed or fail because of runner availability, dependency changes, or site behavior. Add a failure notification path and a manual dispatch option, and verify the platform’s current scheduling guarantees and limits.
- Retries: retry transient network or runner failures with a bounded policy. Avoid unlimited retries; they can create duplicate work or unexpectedly increase API usage.
- Performance: browser startup and page rendering usually dominate a single capture job. Parallelize only within the runner and service limits, and keep a timeout per page so one stalled URL does not block the entire run.
- Cost: self-hosted automation consumes CI minutes and storage; an API may charge per successful capture or plan usage. Calculate monthly volume as URLs × captures per day × days × viewport variants, then compare against current pricing and retention needs.
- Change control: pin dependencies or otherwise manage updates intentionally. A browser or capture-tool update can alter rendering and invalidate visual baselines.
Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| No scheduled run appears | Invalid cron expression, schedule timing assumption, or repository/workflow configuration | Check the workflow syntax and current GitHub Actions schedule documentation. Remember cron is evaluated in UTC. |
| Manual run works but scheduled run fails | Different permissions, missing secrets, or schedule-specific environment | Compare event context, job permissions, secret availability, and logs. Do not assume manually available credentials exist in scheduled runs. |
| Browser or executable missing | The runner lacks a required browser dependency or the install step changed | Follow the capture tool’s current installation guidance and inspect the setup logs. |
| Capture is blank or incomplete | Page not ready, blocked access, incorrect viewport, or lazy content not loaded | Open the URL from the same environment if possible; use a documented readiness wait, confirm authentication, and inspect the saved image. |
| Generated files are not pushed | Insufficient repository permission, no staged changes, or wrong output path | Check job permissions, branch rules, git status, and the path passed to the capture command. |
| Repository grows quickly | Every daily image is retained in Git history | Set a retention policy, use workflow artifacts with suitable retention, or store images outside the repository. |
| Visual diffs are noisy | Dynamic page content, inconsistent viewport, animations, or rotating banners | Use a stable viewport and readiness condition; where supported, hide or neutralize known dynamic regions. |
FAQ
Can Screenshot.rocks take screenshots every day?
The reviewed product description documents mockup creation from existing screenshots, not daily scheduling. Confirm current product documentation before relying on an automated capture feature.
Can I use Screenshot.rocks after the scheduled capture?
Potentially: the stated workflow is to create a mockup from an existing screenshot. Confirm current import, format, and export behavior in its interface.
What time does a GitHub Actions daily schedule run?
The example uses 07:17 UTC. Convert the desired local time to UTC and account for daylight-saving changes if local wall-clock consistency matters.
Should I keep every screenshot?
Keep only the history needed for review or comparison. Daily captures accumulate quickly, especially with multiple URLs and viewport sizes.


