Join the AI Workshop to learn more about AI and how it can be applied to web development. Next cohort February 1st, 2026
The AI-first Web Development BOOTCAMP cohort starts February 24th, 2026. 10 weeks of intensive training and hands-on projects.
We previously saw how to use hx-get to do a GET request.
POST requests are similar, but using hx-post:
<button hx-post="/data"
hx-swap="innerHTML"
hx-target="#data">
Load fresh data
</button>
<div id="data"></div>
If /data returns the same data as the GET request, this works in the same way.
But conceptually POST requests are used to send data to the endpoint.
This is done using forms.
If the element issuing the POST is inside a form, or is a form, all the input fields are sent to the endpoint as form data.
You can configure this behavior by filtering out some fields using hx-params and including other input fields using hx-include.
Typically you have a form like this:
<form
hx-post="/projects"
hx-target="#result">
<input name="name" />
<button type="submit">Add</button>
</form>
This is equivalent to:
<form>
<input name="name" />
<button
type="submit"
hx-post="/projects"
hx-target="#result">
Add
</button>
</form>
Both work in the same way, htmx posts to /projects the data of the form, which in this case means the name input field value.
Note that if you use validation in a form, for example setting a field as required, the request will not be sent if validation fails.
Server-side, for example using Astro, you can get this data using Astro.request.formData():
---
export const partial = true
if (Astro.request.method === 'POST') {
const formData = await Astro.request.formData()
//this prints the form data to the console
console.log(formData)
//FormData { [Symbol(state)]: [ { name: 'name', value: 'my project name' } ] }
}
---
<p>project created</p>
Note that you must configure Astro to be server-rendered in astro.config.mjs:
import { defineConfig } from 'astro/config'
// https://astro.build/config
export default defineConfig({
+ output: 'server'
})