Framejet Screenshot
Capturas de tela PNG/JPEG limpas via MCP remoto ou REST, com navegação multi-etapas orientada por objetivos. Remove banners de cookies e widgets de chat por padrão.
Servidor MCP hospedado
npx add-mcp 'https://framejet.dev/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
API de Screenshot
Um único endpoint. Envie uma URL, receba uma imagem de volta.
Autenticação
Envie sua chave no cabeçalho X-Api-Key ou Authorization: Bearer. Chaves na query string não são suportadas. Onde você não puder enviar um cabeçalho, como em uma tag <img> ou em uma planilha, use uma URL assinada. Obtenha uma gratuitamente na página inicial.
Como sua chave funciona
Digite seu e-mail na página inicial e confirme o link na sua caixa de entrada. Seu navegador gera uma nova chave de API. Copie-a antes de sair; ela nunca é enviada por e-mail nem retornada pelo servidor.
Use o mesmo e-mail no checkout. O pagamento atualiza seu plano sem alterar uma chave de API existente. Se você ainda não tem uma chave, solicite um link de verificação na página inicial.
Perdeu sua chave? Solicite um link de recuperação. A confirmação cria uma chave substituta e invalida a chave antiga imediatamente.
GET /v1/take
curl -H "X-Api-Key: YOUR_KEY" -o shot.png "https://framejet.dev/v1/take?url=https://example.com"
Parâmetros
| Parâmetro | Padrão | Descrição |
|---|---|---|
url | — | Obrigatório. Página http/https a ser capturada. |
X-Api-Key | — | Cabeçalho HTTP. Alternativamente, use Authorization: Bearer. |
format | png | png ou jpeg. |
full_page | false | Capturar toda a altura de rolagem. |
width | 1280 | Largura da viewport, 320–3840. |
height | 800 | Altura da viewport, ainda validada com full_page=true; o conteúdo da página determina a altura final da captura. |
dpr | 1 | Proporção de pixels do dispositivo, 1–3. Veja o guia da API de screenshot retina. |
clean | true | Remover banners de cookies, barras fixas, widgets de chat. |
delay | 0 | Espera extra em ms após o carregamento, máximo 10000. |
cache | true | Defina false para forçar uma captura nova. |
actions | — | Etapas a executar antes da captura, separadas por ;, cada uma verb:arg — click:<css>, type:<css>=<text>, waitfor:<css>, wait:<ms>, scroll:<px>. Máximo de 10 etapas, 15s de espera total. |
goal | — | Descrição em linguagem natural do estado a ser alcançado, terminando com quando parar. Máximo de 300 caracteres. Veja modo objetivo. |
values | — | Strings separadas por | que uma etapa goal pode digitar. Máximo de 10, 200 caracteres cada. A Framejet nunca inventa texto. |
Máximo de 32 milhões de pixels e 4 MB por imagem. Capturas caras podem ser rejeitadas com pixel_limit ou image_too_large. Cada renderizador ativo permite duas capturas simultâneas; excesso de trabalho retorna 429.
Modo objetivo
Use o modo objetivo quando a rota ou os controles variam e você não consegue nomear todos os seletores de forma confiável antecipadamente. Descreva o estado final da página e a Framejet caminha em direção a ele, relendo a página após cada etapa. Se você conhece os seletores, actions também pode clicar, digitar e aguardar controles que aparecem após etapas anteriores. Veja o guia de screenshot após clicar ou pesquisar para ambas as abordagens.
GET /v1/take
?url=https://en.wikipedia.org/
&goal=Search for the Colosseum article, open it, then open its
View history page. Stop when the revision list is visible.
&values=Colosseum
Qualquer texto digitado vem de values e de mais nada — se nenhum deles se encaixa em um campo, a captura falha em vez de adivinhar. A navegação é decidida por um modelo de escolha restrita que seleciona entre os controles realmente presentes na página, então não pode inventar um elemento.
Use actions sempre que você conhecer a página. Etapas de seletor são determinísticas e reproduzíveis. O modo objetivo pode levar vários segundos, é limitado a 12 etapas e 30 segundos, e não garante fazer a mesma escolha duas vezes. Ambos os modos usam um crédito de screenshot quando retornam uma nova imagem. Para testes de regressão visual em particular, use actions — um caminho de captura não determinístico transforma seus diffs em ruído.
Quando o modo objetivo relata que não consegue alcançar o estado solicitado, ele retorna 422 goal_unreached e não custa cota. Um modelo decide quando o objetivo parece completo, então verifique a imagem retornada antes de confiar nela para fluxos de trabalho críticos.
URLs assinadas
Uma URL assinada permite que uma página, um CMS ou uma ferramenta no-code carregue um screenshot diretamente, por exemplo em <img src>, sem expor sua chave de API. Obtenha seu ID de chave e segredo de assinatura uma vez:
curl -H "X-Api-Key: YOUR_KEY" https://framejet.dev/v1/signing-key # { "key_id": "…", "signing_secret": "…" }
Construa a query string com key_id e quaisquer parâmetros de captura, calcule HMAC-SHA256 dessa string exata com o segredo de assinatura, e anexe &sig= com o digest hexadecimal como último parâmetro. Assine os bytes que você envia: não reordene nem re-encode a query depois. Mantenha o segredo de assinatura no seu servidor.
import { createHmac } from "node:crypto"; const q = new URLSearchParams({ url: "https://example.com", key_id: KEY_ID, width: "1280" }).toString(); const sig = createHmac("sha256", SIGNING_SECRET).update(q).digest("hex"); const src = https://framejet.dev/v1/take?${q}&sig=${sig}\;
import hashlib, hmac from urllib.parse import urlencode q = urlencode({"url": "https://example.com", "key_id": KEY_ID, "width": "1280"}) sig = hmac.new(SIGNING_SECRET.encode(), q.encode(), hashlib.sha256).hexdigest() src = f"https://framejet.dev/v1/take?{q}&sig={sig}"
- Alterar qualquer parâmetro invalida a assinatura, então uma URL assinada não pode ser reutilizada para outra página ou configuração.
- Adicione
expires(segundos Unix) antes de assinar para fazer uma URL parar de funcionar após esse horário. - Requisições assinadas sempre usam o cache, e a resposta é pública por um dia, então visualizações repetidas não gastam cota. A primeira captura de cada URL usa um screenshot.
- Substituir sua chave de API altera ambos os valores e invalida todas as URLs assinadas feitas com as antigas.
Resposta
As respostas são private/no-store, exceto URLs assinadas (veja acima). Imagens em cache pertencem à sua conta e expiram após sete dias; acessos repetidos ao cache não gastam cota.
200 com os bytes da imagem (image/png ou image/jpeg). X-Framejet-Cache é HIT ou MISS; X-Framejet-Remaining mostra os screenshots restantes neste mês.
Erros
JSON { "error": "...", "code": "..." }:
| Status | code | Significado |
|---|---|---|
| 401 | no_key / invalid_key | Chave de API ausente ou desconhecida. |
| 403 | bad_signature / url_expired | Uma URL assinada foi alterada, assinada com o segredo errado, ou está além do tempo de expires. |
| 402 | quota_exceeded | Cota mensal atingida. Faça upgrade em preços. |
| 422 | bad_url / blocked_target / target_timeout | A URL de destino é inválida, privada, ou não carregou. |
| 422 | target_error | O destino respondeu com HTTP 400 ou superior, geralmente proteção contra bots (chatgpt.com retorna 403). A Framejet não contorna isso. Nenhuma cota foi usada. |
| 422 | bad_action / bad_goal / bad_values / action_failed | Uma etapa não pôde ser analisada, ou um seletor em actions não correspondeu a nada. Nenhuma cota foi usada. |
| 422 | goal_unreached / values_required | O estado objetivo não foi alcançado, ou um campo precisava de texto que nenhum value fornecido se encaixava. Nenhuma cota foi usada. |
| 500 | capture_failed | Erro nosso — nenhuma cota foi usada. |
Exemplos
JavaScript
const res = await fetch("https://framejet.dev/v1/take?url=https://example.com", { headers: { "X-Api-Key": KEY } }); if (!res.ok) throw new Error(await res.text()); fs.writeFileSync("shot.png", Buffer.from(await res.arrayBuffer()));
Python
r = requests.get("https://framejet.dev/v1/take", params={"url": "https://example.com"}, headers={"X-Api-Key": KEY}) r.raise_for_status() open("shot.png", "wb").write(r.content)
Servidor MCP
A Framejet também é um servidor remoto Model Context Protocol, então você pode dar a um agente de IA (Claude, Cursor, …) a capacidade de tirar screenshots. Adicione um conector apontando para:
Autentique com sua chave de API como um bearer token (Authorization: Bearer YOUR_KEY), ou envie-a como X-Api-Key: YOUR_KEY. Ele expõe uma ferramenta, screenshot, que aceita os mesmos parâmetros acima (url, full_page, width, format, clean, goal, values, …) e retorna a imagem inline. As chamadas usam a mesma cota mensal.
Contato
Dúvidas, limites maiores, bugs: e-mail founder@framejet.dev.