Extract Every Field From an HTML Form

Paste HTML and get a complete inventory of every form control — name, id, type, label, required flag, default value, placeholder, and validation rules — as JSON, Markdown, or CSV. Runs entirely in your browser; nothing is uploaded.

Try:
Form fields

About this tool

Paste the HTML of a page or a single <form> and this tool walks the markup with a real HTML parser and reports every form control it finds<input>, <select>, <textarea>, and optionally <button> — together with everything a developer, tester, or auditor needs to know about it:

Each form is reported with its action, method (lowercased, defaulting to get), id, name, and enctype, so you can see exactly where the data goes.

Worked example

Input HTML:

<form id="signup" action="/register" method="post">
  <label for="email">Email address</label>
  <input type="email" id="email" name="email" required placeholder="[email protected]" maxlength="64">
  <label>Age <input type="number" name="age" min="18" max="120"></label>
  <input type="hidden" name="csrf" value="tok123">
  <button type="submit">Sign up</button>
</form>

Output with Markdown selected:

## Form 0 — POST /register

id: `signup`

| # | Name | Type | Label | Required | Default | Validation |
|---|------|------|-------|----------|---------|------------|
| 1 | `email` | `email` | Email address | yes | — | maxlength=`64` |
| 2 | `age` | `number` | Age | no | — | min=`18`, max=`120` |
| 3 | `csrf` | `hidden` | — | no | `tok123` | — |

The submit button is absent because Include buttons is off by default — buttons are actions, not data fields. Switch it on and a fourth row appears. Choose JSON for the same data as a nested structure, or CSV for one flat row per field that pastes straight into a spreadsheet.

Good uses

Limits and edge cases

FAQ

Why is the submit button missing from my results?

Buttons are excluded by default because they are actions rather than data fields. Turn on Include buttons to add every <button> plus <input> controls of type submit, reset, button, and image.

What happens to inputs that are not inside a <form> tag?

They are not dropped. Any control that sits outside every <form> is collected into one extra group at the end, flagged unattached in JSON output and titled "controls outside any <form>" in Markdown. Modern JavaScript-driven forms are frequently <div>-based with no <form> element at all, and those fields still matter.

If a control carries a form="some-id" attribute — claiming membership in a form it is not nested inside — that attribute is reported as form_attr on the field, but the control stays in the group matching its real position in the document, so the output always mirrors the actual markup.

How is the label for each field worked out?

Four sources are tried in order: a <label for="…"> pointing at the field's id, a <label> that wraps the field, the field's aria-label attribute, and finally its title. If none of those exist the label is empty — which is usually worth fixing, since a field with no label is hard to use with a screen reader.

Can it read a form from a URL instead of pasted HTML?

No. This tool is fully offline — it has no network access at all, which is why your markup never leaves your machine. Fetch the page yourself (View Source, curl, or DevTools → Elements → Copy outerHTML) and paste the result here.

Does it handle messy or invalid HTML?

Yes. Parsing uses the same HTML5 parsing algorithm browsers use, so unquoted attribute values, unclosed <p> and <li> tags, mixed-case tag names, and sloppy nesting all parse the way a browser would read them. That is the main reason to use this rather than a regular expression, which breaks on all of the above.

What is the difference between the "tag" and "type" columns?

tag is the literal element — input, select, textarea, or button. type is the effective control type: for an <input> it is the type attribute, defaulting to text when absent; for a <button> it is the type attribute, defaulting to submit; and for <select> and <textarea> it repeats the tag name, since those elements have no type attribute. Keeping both means a <select> is never confused with <input type="select">, which is not a real thing.

Can I extract just one form from a whole page?

Yes — set Form index to the form's 0-based position in the document (0 for the first form, 1 for the second, and so on). Leave it at -1 to report every form. The index of the unattached group is one past the last real form.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool html-form-field-extractor '<form action="/register" method="post">
  <label for="email">Email</label>
  <input type="email" id="email" name="email" required>
</form>'

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/html-form-field-extractor/?html=%3Cform%20action%3D%22%2Fregister%22%20method%3D%22post%22%3E%0A%20%20%3Clabel%20for%3D%22email%22%3EEmail%3C%2Flabel%3E%0A%20%20%3Cinput%20type%3D%22email%22%20id%3D%22email%22%20name%3D%22email%22%20required%3E%0A%3C%2Fform%3E&format=json&form_index=-1&include_buttons=true&include_hidden=true&include_labels=true

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.