Why this is a REST guide rather than a NuGet SDK page
Snapshot Site has no official .NET package today. A page that invented a package name, methods, or support policy would create false expectations. The stable integration surface is the REST API, which modern .NET applications can call with built-in HTTP and JSON support.
A focused typed client is typically a small amount of code. It should reflect application conventions for dependency injection, options, logging, cancellation, resilience, and storage instead of creating a second infrastructure stack just for screenshots.
Register the client correctly
Prefer IHttpClientFactory in ASP.NET Core
Register a typed or named HttpClient with the base address and a timeout appropriate to rendering work. Inject the API key through options backed by a secret provider. Keep endpoint paths and headers inside the adapter.
Do not instantiate and dispose a new client for every controller call in a long-running service. Managed connection reuse is one of the reasons to follow the framework pattern.
For a command-line job, a single reused client for the process is sufficient. The important rule is to avoid recreating the transport for every item in a batch.
Use operation-specific records
Create separate request and response records for screenshot, analyze, and compare. Their payloads differ and benefit from different validation. Explicit JsonPropertyName attributes remove ambiguity around names such as fullSize and hideCookie when the project has a different global naming policy.
Model only fields the application uses, but include the documented error and message information necessary for operations. Treat a missing required output link as a failure even when deserialization succeeds.
Validate target configuration
Keep target URLs and capture options in a domain-level job configuration. Validate format, viewport, and business permissions before making the request. If users can submit arbitrary URLs, apply the product's destination policy and authorization boundary before they reach the adapter.
Cancellation, timeouts, and background work
Pass a CancellationToken through PostAsJsonAsync, response parsing, and asset download. In ASP.NET Core this may begin with the request token; in a BackgroundService it should come from the worker lifecycle and job deadline.
Browser rendering can take longer than a database lookup or internal JSON endpoint. Choose a bounded request timeout based on observed pages and required delay. Do not set an infinite timeout, and do not copy a two-second internal-service policy that makes legitimate renders fail.
For interactive workflows, decide whether a user should wait or receive a job identifier. Batch, schedule, PDF, and full-page work often belong in a queue or background worker where progress and retries are explicit.
Parse API outcomes carefully
First check the transport response. Then deserialize the JSON and inspect API-level error fields. Some validation or rendering outcomes may arrive as a JSON error payload, so EnsureSuccessStatusCode alone is not a complete success condition.
Convert failures into a small application error model with operation, sanitized target identifier, retryability where available, and message. Avoid logging the API key, authorization headers, or complete URLs that contain private query parameters.
Retry only failures classified as transient. Use bounded exponential backoff with jitter and observe cancellation. Invalid options and authentication failures should fail the job immediately and produce a configuration issue.
Stream generated outputs
The capture response returns a link. When the asset needs durable ownership, download it into application storage. Use HttpCompletionOption.ResponseHeadersRead or an equivalent streaming pattern for large files, validate content type and size, and copy into a file or object-storage stream.
Store the source identifier, request configuration, capture time, and resulting storage key in the same record. A screenshot without its configuration is difficult to reproduce and risky to use as an audit artifact.
Apply an idempotent output key for scheduled or batch work. A retry should resolve to the same intended report or capture slot instead of creating an unrelated duplicate.
C# integration patterns
Background monitoring service
A hosted worker can read approved targets, limit parallel calls with SemaphoreSlim or a bounded channel, compare results with stored baselines, and write review items. The Website Monitoring API explains baseline ownership and alert context.
Report and PDF generation
Build a stable report URL, request format: pdf, validate the result, and stream the document into approved storage. Protect preview routes containing business or customer data and avoid permanent public tokens.
Release evidence
Run a small capture matrix after deployment and attach images or diffs to the release record. Keep viewport and timing fixed so comparisons measure the application rather than configuration drift.
Security and capacity
Use an approved secret provider and restrict access to the typed client. Do not forward arbitrary injected page code from an unauthenticated web request. Sanitize logging and apply retention rules to captures that may contain business-sensitive information.
Bound parallelism according to the plan and workload. A Task.WhenAll over thousands of targets creates a burst; a bounded channel or worker pool provides controlled throughput and easier cancellation.
C# integration checklist
- Register a reusable named or typed
HttpClient.
- Inject the API key from secure server-side configuration.
- Define separate typed models for each operation.
- Propagate cancellation and set realistic bounded timeouts.
- Check transport and JSON application outcomes.
- Stream durable assets into controlled storage.
- Bound parallelism and retry only transient failures.
- Test invalid input, cancellation, partial batches, and download errors.