invalid_parameter

One parameter in the request has a value the API cannot use, most often a number outside its allowed range. The param field names the parameter, so you rarely need to guess. Fix the value and send again; the same request fails every time. This page is part of the error code reference.

HTTP status 400 Bad Request
error.type validation_error
error.param Path of the bad parameter, for example viewport.width
error.retryable false
Credits used 0

Example response

{
  "error": {
    "type": "validation_error",
    "code": "invalid_parameter",
    "message": "viewport.width must be between 1 and 7680",
    "param": "viewport.width",
    "retryable": false,
    "docs": "https://docs.renderscreenshot.com/errors/invalid_parameter"
  },
  "request_id": "req_abc123"
}

param uses the nested JSON path from POST requests. If you sent a flat GET parameter, map it back: width is viewport.width, quality is output.quality, timeout is wait.timeout.

Documented ranges

Parameter GET name Allowed values
viewport.width width 1 to 7680 pixels
viewport.height height 1 to 4320 pixels
viewport.scale scale 1 to 3
output.quality quality 1 to 100 (JPEG and WebP)
wait.timeout timeout Seconds, up to 60 (default 30)
browser.geolocation.latitude / longitude -90 to 90 / -180 to 180

Full details are on the viewport, wait and output pages.

More specific codes

Some parameters have their own validation code. When you see one of these, it means the same thing as invalid_parameter, for one known field:

Code Parameter
invalid_format output.format
invalid_url url
invalid_preset preset
missing_required A required parameter is missing, such as url
invalid_cache_ttl cache.ttl (3,600 to 2,592,000 seconds)
invalid_media_type browser.media (screen or print)
invalid_timezone, invalid_locale browser.timezone (IANA), browser.locale (BCP 47)
invalid_paper_format, invalid_pdf_scale, invalid_pdf_margin PDF options

Write your handler for type: validation_error and read param, and every one of these codes is covered.

Common causes

  • Values from users. A width or quality typed into your form goes straight to the API.
  • Units. wait.timeout is in seconds, while wait.delay is in milliseconds. timeout: 30000 is far over the limit.
  • Retina math. A 2,000 px wide layout with scale: 4 asks for more than the maximum device scale factor of 3.
  • Old configuration. A value that a previous version of your code clamped is now sent as is.

How to fix it

  1. Read error.param and error.message.
  2. Check the value against the ranges above, or the parameter's docs page.
  3. If users set the value, validate it in your own form with the same limits, and show the API message next to the field.
  4. Never retry a 400 automatically.

This function returns field errors for your form instead of throwing, so the user sees which input to change:

// param-errors.mjs (Node 22+): turn a 400 into a message attached to the right form field.
const API = process.env.RS_BASE_URL ?? 'https://api.renderscreenshot.com';

// Map API parameter paths to the fields of your own form.
const FIELD_FOR_PARAM = {
  'viewport.width': 'width',
  'viewport.height': 'height',
  'viewport.scale': 'pixelRatio',
  'output.quality': 'quality',
  'wait.timeout': 'timeout',
};

export async function capture(body) {
  const res = await fetch(`${API}/v1/screenshot`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.RS_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  if (res.ok) return { image: Buffer.from(await res.arrayBuffer()) };

  const { error, request_id } = await res.json();
  if (error.type === 'validation_error') {
    // Never retry: the same body fails the same way every time.
    return {
      fieldErrors: { [FIELD_FOR_PARAM[error.param] ?? 'form']: error.message },
      code: error.code,
      requestId: request_id,
    };
  }
  throw new Error(`${res.status} ${error.code}: ${error.message} (${request_id})`);
}

const result = await capture({ url: 'https://example.com', viewport: { width: 9000 } });
console.log(result.fieldErrors ?? `${result.image.length} bytes`);

With the Ruby SDK, every 400 arrives as RenderScreenshot::ValidationError, with the API code in e.code:

require 'renderscreenshot'

client = RenderScreenshot.client(ENV.fetch('RS_API_KEY'))

begin
  client.take({ url: 'https://example.com', viewport: { width: 9000 } })
rescue RenderScreenshot::ValidationError => e
  # 400s are bugs in the request: report them, never retry them.
  warn "#{e.code}: #{e.message} (#{e.request_id})"
end

Tested on 2026-10-15 with Node 22.18, and Ruby 4.0.7 plus the renderscreenshot gem 1.0.0, against a local mock that applies the documented viewport.width range. A width of 9000 produced { width: 'viewport.width must be between 1 and 7680' } in Node and the matching log line in Ruby.

Related in this topic

Was this page helpful?