lissy93/web-check · error · Error

URL provided is invalid

Error message

URL provided is invalid

What it means

screenshotHandler passes the supplied URL straight to the URL constructor (no scheme prepending). If it throws — missing protocol, invalid characters, malformed host — this error surfaces. Note the stricter contract compared to sibling endpoints: here the scheme is mandatory.

Source

Thrown at api/screenshot.js:77

    await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
    await page.evaluate(() => {
      if (!document.querySelector('body')) {
        throw new Error('No body element found on the page');
      }
    });
    const buffer = await page.screenshot();
    return buffer.toString('base64');
  } finally {
    if (browser) await browser.close().catch(() => {});
  }
};

const screenshotHandler = async (targetUrl) => {
  if (!targetUrl) throw new Error('URL is missing from queryStringParameters');
  try {
    new URL(targetUrl);
  } catch {
    throw new Error('URL provided is invalid');
  }

  log.debug(`request received: ${targetUrl}`);
  try {
    return { image: await directChromiumScreenshot(targetUrl) };
  } catch (directError) {
    log.warn(`direct chromium failed, falling back to puppeteer: ${directError.message}`);
  }
  try {
    return { image: await puppeteerScreenshot(targetUrl) };
  } catch (error) {
    if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) {
      return { skipped: error.message };
    }
    log.error(`puppeteer screenshot failed: ${error.message}`);
    throw error;
  }
};

View on GitHub (pinned to af1a97759f)

Solutions

  1. Include the full scheme: pass https://example.com not example.com
  2. encodeURIComponent the URL when building the query string client-side
  3. Pre-validate with new URL(candidate) in the caller before hitting the endpoint

Example fix

// before
fetch(`/api/screenshot?url=${'example.com'}`); // 500: URL provided is invalid

// after
const target = 'example.com'.startsWith('http') ? 'example.com' : `https://${'example.com'}`;
fetch(`/api/screenshot?url=${encodeURIComponent(target)}`);
Defensive patterns

Strategy: type-guard

Validate before calling

const isValidAbsoluteUrl = (s) => { try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; } };
if (!isValidAbsoluteUrl(url)) return badRequest('url must be absolute with http(s) scheme');

Type guard

const isHttpUrl = (v) => {
  if (typeof v !== 'string') return false;
  try { const u = new URL(v); return /^https?:$/.test(u.protocol); } catch { return false; }
};

Try / catch

try { await screenshotHandler(url); }
catch (e) {
  if (e.message === 'URL provided is invalid') return badRequest('include the scheme, e.g. https://example.com');
  throw e;
}

Prevention

When it happens

Trigger: Calling with 'example.com' (no https://), 'htp://example.com', URLs containing spaces or invalid percent-encoding, or 'https://' with empty host.

Common situations: Users omitting the protocol because other endpoints auto-prepend it, mobile keyboards autocorrecting '://' , or unencoded input copied from chat clients.

Related errors


AI-assisted analysis of lissy93/web-check@af1a97759f (2026-08-27). Data as JSON: /api/errors/ea1761c4bf1871a3. Report an issue: GitHub.