openapi: 3.0.3
info:
  title: Website Screenshot Capture
  description: |
    Capture screenshots or PDFs of any public web page. Supports PNG, JPEG, WebP, and PDF
    output formats. Features include custom viewport sizes, full-page capture, quality control,
    retina scaling (2x/3x), dark mode emulation, element selection via CSS selectors, ad/tracker
    blocking, custom JavaScript injection, and configurable delay for dashboards and JS-heavy pages.

    **Popular use cases:** Power BI dashboard capture, Tableau visualization screenshots,
    Grafana panel snapshots for incident reports, web page archival, social media preview images.
    Use `delay=5000` for dashboards that need time to render charts.

    **Reliability:** Handles sites with self-signed, expired, or invalid SSL certificates.
    Returns actionable suggestions on failure (timeout, unreachable URL, missing selector).

    **Authentication (optional):** Add an `X-API-Key` header for higher limits (5 req/min, 50/day vs anonymous 10/day cap).
    API key holders also get longer max delay (30s vs 10s) — ideal for complex dashboards.
    Get a free API key instantly at https://51-68-119-197.sslip.io/tools/screenshot or POST to `/api/keys`.

    Without a key: 5 requests per minute per IP. With a free key: 5 req/min, 50/day, 500/month.
  version: "2.1.0"
  contact:
    name: Hermes Agent
    email: hermes-agent@agentmail.to
    url: https://51-68-119-197.sslip.io/

externalDocs:
  description: Try this tool in the browser
  url: https://51-68-119-197.sslip.io/tools/screenshot

servers:
  - url: https://51-68-119-197.sslip.io

paths:
  /api/screenshot:
    get:
      operationId: captureScreenshot
      summary: Capture a screenshot or PDF of a web page
      description: |
        Takes a screenshot of the specified URL and returns it as a PNG image or PDF document.
        Results are cached for 1 hour. Rate limited to 5 requests per minute per IP.
      parameters:
        - name: url
          in: query
          required: true
          description: The URL of the web page to capture. Must be a public URL (no private/internal IPs).
          schema:
            type: string
            example: "https://example.com"
        - name: viewport
          in: query
          required: false
          description: "Device viewport preset. Overrides width/height. Options: mobile, tablet, desktop, desktop_hd, macbook, iphone_14, pixel_7, ipad_pro, og, twitter, linkedin."
          schema:
            type: string
            enum: [mobile, mobile_landscape, tablet, tablet_landscape, desktop, desktop_hd, desktop_4k, macbook, iphone_se, iphone_14, iphone_14_pro_max, pixel_7, galaxy_s21, ipad_mini, ipad_pro, linkedin, twitter, facebook, og]
            example: mobile
        - name: width
          in: query
          required: false
          description: "Viewport width in pixels (overridden by viewport preset)."
          schema:
            type: integer
            default: 1280
            maximum: 1920
            example: 1280
        - name: height
          in: query
          required: false
          description: Viewport height in pixels.
          schema:
            type: integer
            default: 720
            maximum: 1080
            example: 720
        - name: full_page
          in: query
          required: false
          description: Capture the entire scrollable page, not just the viewport.
          schema:
            type: string
            enum: ["true", "false"]
            default: "false"
        - name: clip
          in: query
          required: false
          description: "Crop region as x,y,width,height in pixels. Example: 0,0,400,300 captures the top-left 400x300 area. Ignored when full_page=true."
          schema:
            type: string
          example: "0,0,800,600"
        - name: format
          in: query
          required: false
          description: "Output format: png (lossless), jpeg (smaller files, supports quality param), webp (modern, smallest files), or pdf."
          schema:
            type: string
            enum: ["png", "jpeg", "webp", "pdf"]
            default: "png"
        - name: delay
          in: query
          required: false
          description: Extra delay in milliseconds before capture, useful for JavaScript-heavy pages. Anonymous max 10000ms. API key holders max 30000ms (ideal for Power BI, Tableau, Grafana dashboards).
          schema:
            type: integer
            default: 0
            maximum: 30000
            example: 3000
        - name: selector
          in: query
          required: false
          description: CSS selector to capture a specific element instead of the full page. Example "#main-content" or ".hero-banner".
          schema:
            type: string
            example: "#main-content"
        - name: scale
          in: query
          required: false
          description: "Device scale factor for retina/HiDPI screenshots. 1 = standard, 2 = retina, 3 = 3x."
          schema:
            type: integer
            default: 1
            minimum: 1
            maximum: 3
            example: 2
        - name: dark_mode
          in: query
          required: false
          description: Emulate dark color scheme (prefers-color-scheme dark). Sites with dark mode support will render in dark theme.
          schema:
            type: string
            enum: ["true", "false"]
            default: "false"
        - name: quality
          in: query
          required: false
          description: Image quality (1-100). Applies to format=jpeg and format=webp. Lower values = smaller files.
          schema:
            type: integer
            default: 80
            minimum: 1
            maximum: 100
        - name: block_ads
          in: query
          required: false
          description: Block ads, trackers, and cookie consent banners for cleaner screenshots.
          schema:
            type: string
            enum: ["true", "false"]
            default: "false"
        - name: js
          in: query
          required: false
          description: Custom JavaScript to execute before capture. Use to hide elements, click buttons, dismiss popups. Max 2000 characters.
          schema:
            type: string
            example: "document.querySelector('.cookie-banner')?.remove()"
        - name: wait_for
          in: query
          required: false
          description: CSS selector to wait for before capturing. Waits up to 15 seconds for the element to appear. Useful for SPAs and dynamically-loaded content.
          schema:
            type: string
            example: "#main-content"
        - name: http_username
          in: query
          required: false
          description: HTTP Basic Auth username for password-protected pages (e.g., internal Grafana, Kibana dashboards). Requires API key.
          schema:
            type: string
        - name: http_password
          in: query
          required: false
          description: HTTP Basic Auth password. Requires API key.
          schema:
            type: string
        - name: accept_language
          in: query
          required: false
          description: "Browser Accept-Language header for localized screenshots. Sets both the HTTP header and browser locale. Examples: fr-FR, de-DE, ja-JP, pt-BR. Alias: lang."
          schema:
            type: string
            example: "fr-FR"
      responses:
        "200":
          description: Screenshot captured successfully.
          content:
            image/png:
              schema:
                type: string
                format: binary
            image/jpeg:
              schema:
                type: string
                format: binary
            image/webp:
              schema:
                type: string
                format: binary
            application/pdf:
              schema:
                type: string
                format: binary
        "400":
          description: Invalid request (missing URL or private IP).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Screenshot capture failed. Response includes actionable suggestions for common failure types (timeouts, unreachable URLs, missing selectors).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScreenshotError"
        "503":
          description: Server busy — too many concurrent screenshot requests. Retry after a few seconds.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScreenshotError"

  /api/screenshot/batch:
    post:
      operationId: batchScreenshots
      summary: Capture screenshots of multiple URLs in one request (API key required)
      description: |
        Capture up to 10 URLs in a single request. Returns base64-encoded images in JSON.
        Requires an API key. Rate limited to 2 batch requests per minute.
        Perfect for dashboard monitoring, competitive analysis, and automated reporting.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [urls]
              properties:
                urls:
                  type: array
                  items:
                    type: string
                  minItems: 1
                  maxItems: 10
                  description: Array of URLs to screenshot
                  example: ["https://example.com", "https://example.org"]
                format:
                  type: string
                  enum: [png, jpeg, webp]
                  default: webp
                width:
                  type: integer
                  default: 1280
                height:
                  type: integer
                  default: 720
                full_page:
                  type: boolean
                  default: false
                delay:
                  type: integer
                  default: 0
                  description: Wait ms before capture (max 30000 with key)
                block_ads:
                  type: boolean
                  default: true
      responses:
        '200':
          description: Batch results with base64-encoded images
          content:
            application/json:
              schema:
                type: object
                properties:
                  batch_id:
                    type: string
                  total:
                    type: integer
                  succeeded:
                    type: integer
                  failed:
                    type: integer
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                        status:
                          type: string
                          enum: [success, failed]
                        content_type:
                          type: string
                        size_bytes:
                          type: integer
                        data_base64:
                          type: string
                        error:
                          type: string
        '401':
          description: API key required
        '429':
          description: Rate limit exceeded (2 batch requests per minute)

security:
  - ApiKeyAuth: []
  - {}

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        Optional API key for higher rate limits. Get one free at
        https://51-68-119-197.sslip.io/tools/screenshot or POST /api/keys with {} (anonymous, 20/day) or {"email": "you@example.com"} (50/day).
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          example: "Rate limit exceeded. Max 5 requests per minute."
    ScreenshotError:
      type: object
      properties:
        error:
          type: string
          example: "Screenshot failed: Timeout 30000ms exceeded"
        suggestions:
          type: array
          items:
            type: string
          description: Actionable retry suggestions based on the failure type.
          example:
            - "Try adding delay=5000 for slow-loading pages"
            - "Try wait_for=body to wait for content to load"
            - "Complex SPAs (GitHub, Figma) may need delay=10000"
