Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Detect HTML5 validation in PhantomJS by running feature and behavior checks inside the page with page.evaluate(). First verify that a control exposes checkValidity() and validity; then deliberately violate a constraint such as required and confirm that the method returns false. Test the exact PhantomJS executable and version you deploy, because API presence does not prove that every constraint—or browser-visible validation UI—is implemented.

What you are actually testing

HTML5 validation has several layers that should not be treated as one feature:

  • API exposure: does a form control have a callable checkValidity() method?
  • Validity state: does the control expose a validity object that describes constraint results?
  • Constraint behavior: does a known-invalid value actually fail, for example an empty required field?
  • Interactive validation: does form submission (or reportValidity()) show an error, focus the field, or otherwise provide browser UI?

These observations are related but independent. A PhantomJS build can expose a method while handling only some constraints, and a script-level failure result does not establish that a validation bubble or focus change is available.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prerequisites and test conditions

  • Run the script with the PhantomJS binary used by your application, not a different globally installed copy.
  • Record the executable version with the test result. PhantomJS uses QtWebKit, and WebKit version numbers alone are not a reliable compatibility indicator.
  • Keep JavaScript enabled. PhantomJS page settings default javascriptEnabled to true, and settings apply during the initial page.open() call.
  • Use simple, serializable values when passing arguments into or returning values from page.evaluate().

Feature detection is safer than inferring support from a browser-engine label. Even when a feature is detected, PhantomJS documentation cautions that support is not guaranteed to be complete; test the level your page requires.

Minimal feature-and-behavior probe

The following self-contained script creates a required input in the page context, checks the two APIs, and exercises an intentionally invalid value.

var page = require('webpage').create();

page.open('about:blank', function (status) {
  if (status !== 'success') {
    console.error('Could not open test page: ' + status);
    phantom.exit(1);
    return;
  }

  var result = page.evaluate(function () {
    var input = document.createElement('input');
    input.required = true;
    input.value = '';

    var hasCheckValidity = typeof input.checkValidity === 'function';
    var hasValidity = !!input.validity;
    var invalidRequiredFieldIsRejected = hasCheckValidity
      ? input.checkValidity() === false
      : false;

    return {
      hasCheckValidity: hasCheckValidity,
      hasValidity: hasValidity,
      invalidRequiredFieldIsRejected: invalidRequiredFieldIsRejected
    };
  });

  console.log('PhantomJS ' + phantom.version.major + '.' +
    phantom.version.minor + '.' + phantom.version.patch);
  console.log(JSON.stringify(result));
  phantom.exit();
});

Save it as detect-validation.js and run phantomjs detect-validation.js. A fully positive result looks like this shape:

{"hasCheckValidity":true,"hasValidity":true,"invalidRequiredFieldIsRejected":true}

The first two properties report API availability. The third is a behavior assertion: an empty control marked required was rejected. If the method is missing, the script deliberately reports the behavior check as false rather than pretending the constraint passed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test the constraints your form actually uses

A required-field probe is only one test. Add a separate case for every rule on which your application depends. The following evaluator returns individual results without relying on browser error UI.

var results = page.evaluate(function () {
  function check(control) {
    var callable = typeof control.checkValidity === 'function';
    return {
      hasCheckValidity: callable,
      hasValidity: !!control.validity,
      rejected: callable ? control.checkValidity() === false : false
    };
  }

  var required = document.createElement('input');
  required.required = true;
  required.value = '';

  var email = document.createElement('input');
  email.type = 'email';
  email.value = 'not-an-email';

  var pattern = document.createElement('input');
  pattern.pattern = '^[0-9]+$';
  pattern.value = 'abc';

  var range = document.createElement('input');
  range.type = 'number';
  range.min = '10';
  range.max = '20';
  range.value = '5';

  return {
    required: check(required),
    email: check(email),
    pattern: check(pattern),
    range: check(range)
  };
});
console.log(JSON.stringify(results));

Use the same attributes, values, and control types as the production form. A passing required test cannot be generalized to pattern, type="email", min, or max. If a rule is conditional on a form, append the control to a form in the evaluator and test the same submission path used by the application.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Inspecting ValidityState

When validity exists, inspect the flags relevant to your diagnostics. Property availability and flag correctness should both be asserted.

var state = page.evaluate(function () {
  var input = document.createElement('input');
  input.required = true;
  input.value = '';
  var valid = typeof input.checkValidity === 'function'
    ? input.checkValidity()
    : null;

  return {
    valid: valid,
    validityPresent: !!input.validity,
    valueMissing: input.validity ? !!input.validity.valueMissing : null,
    customError: input.validity ? !!input.validity.customError : null
  };
});
console.log(JSON.stringify(state));

Do not fail a test merely because an optional flag is absent in an older implementation unless your application reads that flag. Define the minimum contract explicitly—for example, “required must reject an empty value”—and report every other observation separately.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Programmatic checks versus interactive validation

checkValidity() is a query-like, programmatic operation. It returns false when a constraint is violated and can be used without submitting the form. Interactive validation is different: it is associated with form submission unless the form has novalidate, or with an explicit reportValidity() call. Interactive behavior can include focus movement and a browser-rendered message.

Therefore, a true checkValidity() result proves only the script-observable behavior you tested. If your acceptance criteria include a visible bubble, focus placement, or submission blocking, write a separate test in the target build. For example:

var interactive = page.evaluate(function () {
  var form = document.createElement('form');
  var input = document.createElement('input');
  input.required = true;
  form.appendChild(input);
  document.body.appendChild(form);

  var hasReport = typeof input.reportValidity === 'function';
  var reportResult = hasReport ? input.reportValidity() : null;
  return {
    hasReportValidity: hasReport,
    reportResult: reportResult,
    activeElementIsInput: document.activeElement === input
  };
});
console.log(JSON.stringify(interactive));

Interpret this as an observation, not a universal compatibility verdict. Headless rendering may not expose a useful visual surface, and a build can implement programmatic checks without reproducing interactive desktop behavior.

Rank #3
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Using a real page instead of about:blank

The synthetic probe isolates the engine. To test your application, open its URL and evaluate the controls after the page has loaded. Select a representative control by an ID or CSS selector and return only serializable data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var page = require('webpage').create();
page.open('https://example.test/signup', function (status) {
  if (status !== 'success') {
    console.error('Open failed: ' + status);
    phantom.exit(1);
    return;
  }

  var result = page.evaluate(function () {
    var input = document.querySelector('#email');
    if (!input) return { found: false };
    return {
      found: true,
      hasCheckValidity: typeof input.checkValidity === 'function',
      hasValidity: !!input.validity,
      valid: typeof input.checkValidity === 'function'
        ? input.checkValidity()
        : null
    };
  });

  console.log(JSON.stringify(result));
  phantom.exit();
});

If the form is populated asynchronously, wait for a known selector or application-ready condition before evaluating. Otherwise you may be testing a missing control rather than validation support.

Troubleshooting failed probes

hasCheckValidity is false

You are running a build that does not expose the method on that control, JavaScript was disabled, or the evaluator did not run in the page context. Confirm page settings before page.open(), print the PhantomJS version, and verify that the function passed to page.evaluate() contains no references to PhantomJS-only variables.

validity exists but the invalid test passes

Presence is not behavior. Check that the constraint was assigned before the assertion, that the value really violates it, and that you are testing the intended control type. Then add a dedicated case for the exact rule.

The real-page selector returns no control

The page may still be loading, the selector may differ in the deployed markup, or a script may create the form later. Return a found flag, wait for the application’s readiness condition, and capture console or network diagnostics separately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The script reports success but users see no error bubble

This is the expected distinction between programmatic and interactive validation. Test submission and reportValidity() independently, and do not infer visual UI support from checkValidity().

Results differ between machines

Compare the exact PhantomJS executable, version, page settings, URL, and test data. Do not substitute a WebKit version number for a feature test, and do not generalize one binary’s result to every PhantomJS release.

Make the check part of a regression suite

  • Print the PhantomJS version beside every result.
  • Keep synthetic tests for engine behavior and real-page tests for integration behavior.
  • Store one assertion per required constraint and fail with a useful message.
  • Run the suite against the production-like page settings, including JavaScript and any authentication or locale setup.
  • Treat interactive UI requirements as a separate acceptance category.

This approach gives you a reproducible answer to “does this build support the validation contract we need?” rather than an overbroad yes-or-no claim about HTML5.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean image or PDF of a validation state rather than engine compatibility testing, ScreenshotNeo can capture the page through one request. It accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the ScreenshotNeo API documentation for options such as custom JavaScript, waiting for a selector, full-page lazy-image loading, device presets, CSS hiding, headers, cookies, and PDFs.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Does a true result guarantee every HTML5 rule works?

No. It confirms only the method, state object, and deliberately tested constraint. Add independent tests for each rule your form uses.

Can I infer support from PhantomJS’s WebKit version?

No. Implementations can differ, so feature-detect and run the behavior test in the target executable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why test interactive validation separately?

Because submission-time validation and reportValidity() involve browser interaction that is distinct from querying checkValidity().

Frequently Asked Questions

Does a true result guarantee every HTML5 rule works?

No. It confirms only the method, state object, and deliberately tested constraint. Add independent tests for each rule your form uses.

Can I infer support from PhantomJS’s WebKit version?

No. Implementations can differ, so feature-detect and run the behavior test in the target executable.

Why test interactive validation separately?

Because submission-time validation and reportValidity() involve browser interaction that is distinct from querying checkValidity().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.