API Documentação
URL base: https://yhfdghkh6544.com/v1. Todos os endpoints usam HTTP padrão. Os parâmetros podem ser enviados na cadeia de consulta (GET) ou no corpo JSON (POST).
Início rápido
- Registe-se gratuitamente e crie uma API Key na página «API Key» da consola.
- Inclua a API Key no cabeçalho
X-Access-Keye faça um pedido ao endpoint de captura:
curl "https://yhfdghkh6544.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $SNAPI_KEY" \
-o screenshot.pngAutenticação
Todos os pedidos exigem uma API Key, que pode ser enviada de uma das seguintes formas:
- Cabeçalho
X-Access-Key: snp_…(recomendado para pedidos a partir do servidor) - Parâmetro de consulta
access_key=snp_… - URL assinado (para incluir o endereço numa página sem expor o segredo)
A API Key só é apresentada em texto simples uma vez, no momento da criação. Guarde-a em segurança. Se for exposta, pode desativá-la na consola.
Capturas de ecrã
/v1/screenshot/v1/screenshotParâmetros exclusivos das capturas de ecrã:
| Parâmetro | Tipo | Valor predefinido | Descrição |
|---|---|---|---|
| format | enum | png | png, jpeg ou webp. |
| device_scale_factor | number | 1 | Fator de escala de 1–3. O valor 2 oferece nitidez Retina, com um ficheiro cerca de 4 vezes maior. |
| quality | integer | 80 | Qualidade JPEG / WebP, 1–100. |
| full_page | boolean | false | Captura a página inteira. Percorre a página ecrã a ecrã para ativar o carregamento diferido, até uma altura máxima de 20,000 píxeis. |
| selector | string | — | Captura apenas o primeiro elemento correspondente a este seletor CSS. Não pode ser usado com full_page. |
Parâmetros comuns às capturas de ecrã e aos PDF:
| Parâmetro | Tipo | Valor predefinido | Descrição |
|---|---|---|---|
| url | string | — | Endereço da página a capturar, com http ou https. Use este parâmetro ou html, não ambos. O fragmento # do URL é preservado, permitindo capturar diretamente a página correspondente em aplicações de página única com encaminhamento por hash (como https://app.com/#/report/1). |
| html | string | — | Envie HTML diretamente (máximo de 2 MB). Apenas POST. |
| viewport_width | integer | 1280 | Largura da área de visualização, 320–3840. Abaixo de 768, a página é renderizada como num dispositivo móvel. |
| viewport_height | integer | 800 | Altura da área de visualização, 200–3840. |
| wait_until | enum | networkidle | Estratégia de espera: domcontentloaded (a mais rápida, ideal para páginas estáticas), load ou networkidle (acompanha todos os pedidos desde a abertura da página e, após o carregamento, só captura quando não houver pedidos em curso durante 500 milissegundos consecutivos; espera até mais 8 segundos, ideal para aplicações de página única). |
| wait_for_selector | string | — | Após carregar a página, espera que um elemento correspondente a este seletor CSS apareça e fique visível antes de capturar, até 10 segundos. Se não aparecer, devolve selector_not_found (sem cobrança). Ideal para aplicações de página única que renderizam conteúdo com atraso através de temporizadores ou animações, sem depender de pedidos de rede, como .chart-ready. |
| delay | integer | 0 | Atraso adicional em milissegundos após a espera, 0–10000. Útil para aguardar animações ou componentes com carregamento diferido. |
| block_ads | boolean | true | Bloqueia pedidos a domínios de publicidade e rastreamento. |
| block_cookie_banners | boolean | true | Oculta as janelas de consentimento de cookies. |
| dark_mode | boolean | false | Simula prefers-color-scheme: dark. |
| hide_selectors | string | — | Lista de seletores CSS dos elementos a ocultar, por exemplo .ad,#popup. |
| cache | boolean | true | Define se deve procurar na cache. Com false, força uma nova renderização, mas o resultado continua a ser guardado na cache. |
| cache_ttl | integer | 86400 | Prazo de validade da cache em segundos, 60–2592000. |
| response_type | enum | binary | binary devolve o ficheiro diretamente; json devolve o endereço do ficheiro e os metadados. |
Capturar aplicações de página única (React, Vue, etc.):A página é capturada num navegador real, após a execução do JavaScript. A opção predefinida networkidle espera que a página termine de obter os dados. Se o conteúdo só for renderizado depois, através de temporizadores ou animações, use wait_for_selector para indicar um elemento que sinalize que o conteúdo está pronto. Se não houver um elemento adequado, use delay para esperar mais um pouco.
/v1/pdf/v1/pdfCada PDF consome 2 unidades da quota. Antes da impressão, a página é percorrida para ativar o carregamento diferido. Além dos parâmetros comuns, são suportados:
| Parâmetro | Tipo | Valor predefinido | Descrição |
|---|---|---|---|
| paper | enum | a4 | Formato do papel: a4 ou letter. Se a página definir uma regra @page, essa configuração tem prioridade. |
| print_background | boolean | true | Imprime cores e imagens de fundo. |
| pdf_media | enum | print usa os estilos de impressão; screen usa os estilos de ecrã (o resultado corresponde ao que vê). |
curl -X POST "https://yhfdghkh6544.com/v1/pdf" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Relatório trimestral</h1><p>Corpo do texto…</p>", "paper": "a4"}' \
-o report.pdfRespostas
Por predefinição (response_type=binary), o ficheiro é devolvido diretamente, com Content-Type correspondente ao formato. Cabeçalhos de resposta:
X-Request-Id: ID do pedido, a indicar ao comunicar um problemaX-Snapi-Cache:HITouMISSX-Snapi-Truncated: true: a página inteira foi cortada por exceder 20,000 píxeisX-Snapi-Format-Changed: webp: PNG convertido automaticamente em WebP por exceder 5 MB (não há conversão se format=png for especificado explicitamente)
Com response_type=json, são devolvidos o endereço do ficheiro e os metadados:
curl -X POST "https://yhfdghkh6544.com/v1/screenshot" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "response_type": "json"}'
# Devolve
{
"url": "https://yhfdghkh6544.com/i/3f/3f9c….png",
"cache_hit": false,
"duration_ms": 1284,
"format": "png",
"width": 1280,
"height": 800,
"request_id": "req_01j…"
}URL assinados
Quer incluir o endereço da captura diretamente em <img src> sem expor a API Key? Calcule a assinatura no seu servidor com o segredo associado à API Key (disponível na página API Key da consola):
canonical = Ordene todos os parâmetros, exceto signature, por ordem lexicográfica dos nomes,
formate cada entrada como k=urlencode(v) (RFC 3986, com os espaços codificados como %20) e una-as com &
signature = hex(HMAC-SHA256(secret, canonical))Uma assinatura válida autentica o pedido. Qualquer alteração a um parâmetro (por exemplo, a url) invalida a assinatura. O parâmetro opcional expires (segundos Unix) é incluído na assinatura; após a expiração, é devolvido signature_expired. Para atualizar a cache, altere um parâmetro sem efeito (como v=2) e volte a assinar. Os URL assinados só suportam GET.
import crypto from "node:crypto";
// Codificação RFC 3986 (espaços como %20), de acordo com as regras do servidor
const enc = (v) =>
encodeURIComponent(v).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
function signedUrl(params, accessKey, secret) {
const all = { ...params, access_key: accessKey };
const canonical = Object.keys(all).sort().map((k) => `${k}=${enc(String(all[k]))}`).join("&");
const signature = crypto.createHmac("sha256", secret).update(canonical).digest("hex");
return `https://yhfdghkh6544.com/v1/screenshot?${canonical}&signature=${signature}`;
}
const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY, SECRET);
// <img src={src} alt="Pré-visualização da página web" />Cache
Os pedidos com parâmetros idênticos usam a cache (omitir um parâmetro equivale a enviar explicitamente o valor predefinido; os parâmetros de autenticação e de cache não entram na comparação). Quando há um resultado em cache, o modo binário devolve um redirecionamento 302 para o endereço do ficheiro, com Cache-Control; o navegador segue o redirecionamento e guarda o ficheiro em cache automaticamente. O modo JSON devolve cache_hit: true.
Os resultados obtidos da cache não são faturados.Pedidos simultâneos com os mesmos parâmetros geram apenas uma renderização.
Limites e faturação
- Só são faturados os pedidos bem-sucedidos (2xx) que não usem a cache: 1 unidade por captura de ecrã e 2 por PDF.
- Os tempos limite excedidos, as falhas de renderização, os erros do site de destino, os parâmetros inválidos e as falhas de autenticação não consomem quota.
- A quota é reposta no início de cada mês (UTC). O plano gratuito inclui 100 unidades por mês; após esgotá-las, é devolvido quota_exceeded.
- Exceder o limite de pedidos por segundo ou de pedidos simultâneos devolve 429. O cabeçalho de resposta Retry-After indica o tempo de espera recomendado em segundos.
- Tempo máximo de renderização: 30 segundos; volume máximo de transferência por página: 50 MB; tamanho máximo do ficheiro gerado: 50 MB.
Consulte os limites de cada plano: Preços.
Códigos de erro
Todas as respostas de erro usam JSON:
{
"error": {
"code": "render_failed",
"message": "target responded with an error status",
"upstream_status": 404,
"request_id": "req_01j…"
}
}| HTTP | code | Significado | Faturado |
|---|---|---|---|
| 400 | invalid_params | Parâmetro em falta ou fora do intervalo permitido; message indica qual | Não |
| 400 | html_too_large | html excede 2 MB | Não |
| 401 | unauthorized | API Key em falta, inválida ou desativada | Não |
| 401 | signature_invalid | A assinatura não corresponde (parâmetros alterados ou segredo incorreto) | Não |
| 401 | signature_expired | O prazo expires do URL assinado já expirou | Não |
| 403 | url_blocked | O acesso ao endereço de destino não é permitido (por exemplo, endereços de rede privada ou localhost) | Não |
| 408 | render_timeout | A renderização excedeu 30 segundos | Não |
| 422 | render_failed | O site de destino devolveu 4xx/5xx, houve uma falha de DNS ou um erro de certificado; inclui upstream_status | Não |
| 422 | selector_not_found | selector não corresponde a nenhum elemento ou a espera por wait_for_selector excedeu o tempo limite | Não |
| 422 | too_many_redirects | Mais de 5 redirecionamentos | Não |
| 429 | rate_limited | Limite de pedidos por segundo excedido; tente novamente de acordo com Retry-After | Não |
| 429 | concurrency_exceeded | Limite de pedidos simultâneos excedido | Não |
| 429 | quota_exceeded | Quota mensal esgotada (plano gratuito) | Não |
| 429 | too_many_batches | Mais de 5 tarefas em lote por concluir em simultâneo | Não |
| 500 | internal | Erro do servidor; contacte-nos e indique request_id | Não |
Lotes assíncronos
/v1/batch/v1/batch/{id}Envie 1–100 URL de uma só vez. O endpoint devolve imediatamente um ID de tarefa (HTTP 202) e as capturas são processadas uma a uma em segundo plano. Ideal para capturas em lote sem manter a ligação aberta. Pode consultar periodicamente o estado ou definir webhook_url para receber uma notificação quando tudo estiver concluído. A autenticação é igual à do endpoint síncrono (apenas por cabeçalho ou pelo parâmetro access_key; não suporta URL assinados).
| Parâmetro | Tipo | Valor predefinido | Descrição |
|---|---|---|---|
| type | enum | screenshot | screenshot (captura de ecrã) ou pdf. |
| urls | string[] | — | URL a processar, de 1–100. Se algum for inválido, o pedido inteiro devolve 400 e message indica a posição do URL. |
| options | object | {} | Parâmetros comuns a todos os URL, iguais aos do endpoint síncrono (como full_page, format, viewport_width, cache_ttl). Não podem incluir url, html ou response_type. |
| webhook_url | string | — | Opcional. Endereço a notificar quando tudo estiver concluído. Consulte «Notificação de conclusão». |
curl -X POST "https://yhfdghkh6544.com/v1/batch" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "screenshot",
"urls": ["https://example.com", "https://example.org"],
"options": { "full_page": true, "format": "webp" },
"webhook_url": "https://your-app.com/hooks/snapi"
}'
# Devolve 202
{
"id": "bat_01j…",
"type": "screenshot",
"status": "queued",
"total": 2, "succeeded": 0, "failed": 0,
"created_at": "2026-10-18T09:30:00Z", "completed_at": null,
"webhook": { "url": "https://your-app.com/hooks/snapi", "status": "none", "attempts": 0 },
"items": [
{ "index": 0, "url": "https://example.com", "status": "pending", "result": null, "error": null },
{ "index": 1, "url": "https://example.org", "status": "pending", "result": null, "error": null }
]
}Consultar o progresso: o estado da tarefa, status, passa por queued (em fila), running (em processamento) e completed (tudo concluído, com ou sem sucesso). O estado de cada URL é pending, running, succeeded ou failed. Em caso de sucesso, result contém o endereço do ficheiro; em caso de falha, error contém o código de erro (igual ao do endpoint síncrono).
curl "https://yhfdghkh6544.com/v1/batch/bat_01j…" -H "X-Access-Key: $SNAPI_KEY"
{
"id": "bat_01j…",
"status": "completed",
"total": 2, "succeeded": 1, "failed": 1,
"completed_at": "2026-10-18T09:30:12Z",
"items": [
{
"index": 0, "url": "https://example.com", "status": "succeeded", "duration_ms": 1830,
"result": { "url": "https://yhfdghkh6544.com/i/3f/3f9c….webp", "mime": "image/webp", "width": 1280, "height": 2410, "cache_hit": false },
"error": null
},
{
"index": 1, "url": "https://example.org", "status": "failed", "duration_ms": 640,
"result": null,
"error": { "code": "render_failed", "message": "target responded with an error status" }
}
]
}- Aplicam-se as mesmas regras de faturação do endpoint síncrono: cada URL processado com sucesso consome 1 unidade por captura de ecrã ou 2 por PDF. Os resultados da cache e as falhas não consomem quota.
- Se a quota já estiver esgotada ao submeter o pedido, é devolvido
quota_exceededde imediato. Se se esgotar durante o processamento, os URL restantes falham comquota_exceeded. - Cada conta pode ter até 5 tarefas em lote por concluir em simultâneo. Acima desse limite, é devolvido
too_many_batches. - A validade dos ficheiros gerados é definida por
options.cache_ttl(por predefinição, 1 dia). Transfira-os e guarde-os antes de expirarem. - Nos resultados da consulta e nas notificações,
webhook.urlé apresentado apenas até ao caminho, sem a cadeia de consulta.
Notificação de conclusão
Se definir webhook_url, enviaremos um pedido POST para esse endereço quando a tarefa estiver totalmente concluída. O corpo do pedido é JSON: { "event": "batch.completed", "batch": { … } }, em que batch é exatamente igual à resposta do endpoint de consulta. Cabeçalhos do pedido:
X-Snapi-Signature: t=1760779812,v1=5d3f…:té a hora de envio (segundos Unix) ev1é a assinaturaX-Snapi-Event: batch.completed,X-Snapi-Delivery-Attempt: 1(número da tentativa de entrega)
v1 = hex(HMAC-SHA256(secret, t + "." + Corpo original do pedido))
secret é o segredo de assinatura associado à API Key usada para submeter a tarefa (disponível na página API Key da consola).- Devolva uma resposta 2xx no prazo de 10 segundos; caso contrário, a entrega será considerada falhada. Em caso de falha, serão feitas novas tentativas após 10 segundos, 1 minuto e 5 minutos (até 4 tentativas no total).
- Em casos muito raros, pode receber notificações duplicadas para a mesma tarefa. Use
batch.idpara eliminar duplicados. - Para verificar a assinatura, faça o cálculo com os bytes originais recebidos e confirme que a diferença entre
te a hora atual não excede alguns minutos, para evitar ataques de repetição. - O URL de callback deve ser um endereço http(s) acessível publicamente e não pode apontar para uma rede interna.
import crypto from "node:crypto";
// rawBody tem de conter os bytes originais recebidos, sem aplicar JSON.parse e voltar a serializar
function verifySnapiWebhook(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; // Proteção contra ataques de repetição
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const got = Buffer.from(parts.v1 ?? "");
return got.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), got);
}
// verifySnapiWebhook(req.rawBody, req.headers["x-snapi-signature"], SNAPI_SECRET)Consultar utilização
/v1/usagecurl "https://yhfdghkh6544.com/v1/usage" -H "X-Access-Key: $SNAPI_KEY"
{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }Verificação de estado
/v1/healthNão requer autenticação. Devolve o estado do nó e do conjunto de navegadores (total, ocupados e disponíveis).