# HTML form action and method, explained

> HTML form action and method explained simply, plus the name attribute and GET vs POST, with examples you can copy into any website form.

Developers

HTML form action and method explained simply, plus the name attribute and GET vs POST, with examples you can copy into any website form.

By [Venkatesh](https://www.linkedin.com/in/ageven/) 6 November 2026 · 6 min read

![Cover image: HTML form action and method, explained, a FormDoc guide](https://www.formdoc.dev/images/blog/html-form-attributes-explained.png)

The HTML form `action` and `method` attributes decide where a form’s data goes and how it gets there. `action` is the URL that receives the submission. `method` is either `GET`, which puts the data in the URL, or `POST`, which sends it in the request body. For contact forms and anything that sends a message, use `POST` with an `action` that points at a server or form backend. Then give every input a `name`, because fields without one are never sent.

## The three attributes that matter most

A working form needs very little:

```html
<form action="https://api.formdoc.dev/v1/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>
```

Three things make this form send data: the `action` on the form, the `method` on the form, and the `name` on each field. Everything else (labels, placeholders, styling) helps people, but doesn’t change what the browser sends.

## The action attribute

`action` is the address the browser sends the data to. It can be:

-   **A full URL**, such as a form backend endpoint. This is the usual choice for static sites.
-   **A relative path**, such as `/contact`, when your own server handles the form.
-   **Left out**, in which case the form posts back to the current page’s URL. On a static site that means the data goes nowhere useful.

A common mistake is an `action` that points at a file that doesn’t exist, like `send.php` on a host that doesn’t run PHP. The browser sends the data, gets an error page back, and the message is lost. If your host only serves files, point `action` at something that can receive posts. [What is a form backend](https://www.formdoc.dev/blog/what-is-a-form-backend/) explains that option.

Avoid `action="mailto:..."` too. It hands the data to the visitor’s email app instead of sending it, and the [mailto form guide](https://www.formdoc.dev/blog/mailto-form-problems/) covers why that so often fails.

## The method attribute: GET vs POST

`method` has two values you’ll use in practice.

**GET** adds the field values to the end of the URL as a query string, like `/search?q=shoes&size=9`. It’s meant for reading, not changing anything. Search boxes and filters are the classic use: the result page can be bookmarked and shared.

**POST** sends the field values in the body of the request, out of sight of the address bar. It’s meant for actions that change something, like sending a message, signing up or placing an order.

|  | GET | POST |
| --- | --- | --- |
| Where the data goes | In the URL | In the request body |
| Visible in address bar and history | Yes | No |
| Can be bookmarked or shared | Yes | No |
| Size | Limited by URL length | Much larger |
| Good for | Search, filters, pagination | Contact forms, sign-ups, anything that sends or saves |
| Default if `method` is missing | Yes | No |

That last row catches people out. If you forget `method="POST"`, the browser uses GET, and your visitor’s name, email and message end up in the URL, in browser history and possibly in server logs. Always set `method="POST"` on forms that send personal details.

FormDoc’s submit endpoint expects `POST`.

## The name attribute

`name` is the key each value is sent under. When the form above is submitted, the browser sends something like:

```
access_key=YOUR_ACCESS_KEY&email=asha%40example.com&message=Hello
```

The rules are simple:

1.  **No `name`, no data.** An input without a `name` is skipped completely. This is the most common reason a field “doesn’t arrive”.
2.  **Names should be clear.** Whatever you choose is what you’ll see in the notification email, so `phone` beats `field_3`.
3.  **Same name, several values.** Checkboxes that share a name send one value per ticked box. Radio buttons that share a name let the visitor pick one.
4.  **`id` is not `name`.** `id` connects a `label` to its input. `name` is what gets sent. Most fields need both.

```html
<label for="phone">Phone</label>
<input id="phone" type="tel" name="phone">
```

Checkbox groups are worth a quick example, because they show how one name can carry several answers:

```html
<input type="checkbox" id="web" name="services" value="Web design">
<label for="web">Web design</label>
<input type="checkbox" id="seo" name="services" value="SEO">
<label for="seo">SEO</label>
```

If the visitor ticks both, the browser sends `services` twice, once with each value. A checkbox that isn’t ticked sends nothing at all, so don’t expect a “no” value to arrive. If you need a clear yes or no, use two radio buttons with the same name instead.

Some names have a special meaning to a form backend. In FormDoc, `access_key`, `subject`, `from_name`, `redirect`, `replyto` and `botcheck` are reserved: they control the email and the response instead of appearing as ordinary fields. Name your visitor’s address field `email` and replies to the notification go straight to them.

## Other attributes worth knowing

A few more attributes are useful once the basics work:

-   **`enctype`** sets how the body is encoded. The default suits text fields, so you rarely need to change it for a contact form.
-   **`autocomplete`** on inputs (`name`, `email`, `tel`) helps browsers fill fields correctly.
-   **`required`** and `type="email"` let the browser catch missing or badly formatted values before sending.
-   **`novalidate`** on the form turns that browser checking off. Leave it off unless you’re doing your own validation in JavaScript.
-   **`target`** controls where the response opens. You almost never need it.

## Putting it together

Here is a complete form with every attribute doing its job:

```html
<form action="https://api.formdoc.dev/v1/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
  <input type="hidden" name="subject" value="New enquiry">

  <label for="name">Name</label>
  <input id="name" type="text" name="name" autocomplete="name" required>

  <label for="email">Email</label>
  <input id="email" type="email" name="email" autocomplete="email" required>

  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>
```

The full set of fields and responses is in the [API reference](https://www.formdoc.dev/docs/api-reference/), and [how to send an HTML form to email without PHP](https://www.formdoc.dev/blog/html-form-to-email-without-php/) walks through getting a key and testing.

## Common questions

### What happens if I leave out the action attribute?

The form submits to the URL of the page it’s on. If that page is a static file, the data is ignored and the page simply reloads. Always set `action` to the URL that should receive the submission.

### Should a contact form use GET or POST?

POST. A contact form sends personal details and creates something new (a message), which is exactly what POST is for. GET would put the visitor’s details in the URL and browser history.

### Why is one of my fields missing from the email?

Almost always because the input has no `name` attribute, or two fields share a name by accident. Check each input in your HTML and give it a unique, descriptive `name`.

## Next step

Once your attributes are right, the form only needs somewhere to send. The [docs](https://www.formdoc.dev/docs/) show the setup for your platform, and you can get a free access key at [https://app.formdoc.dev/new](https://app.formdoc.dev/new) and point your `action` at it in a couple of minutes.

Written by**[Venkatesh](https://www.linkedin.com/in/ageven/)**
