HTMX hx-post Attribute
The hx-post attribute sends a POST request to the server when an element is triggered. You use POST when you want to send data to the server — such as a new comment, a form submission, or a record to save. The server processes the data and returns an HTML fragment, which HTMX places into the page.
GET vs POST: A Quick Reminder
| Method | Purpose | Sends Data | Common Use |
|---|---|---|---|
| GET | Fetch data | Only in URL (query string) | Loading a page, searching |
| POST | Send data | In the request body (hidden) | Creating, submitting, saving |
Basic Syntax
<button hx-post="/save-item" hx-target="#status"> Save Item </button> <div id="status"></div>
When the user clicks "Save Item," HTMX sends a POST request to /save-item. The server processes the request and returns an HTML fragment — for example, a success message — which HTMX places into #status.
Posting Form Data
The most common use of hx-post is on a form. When you put hx-post on a <form> element, HTMX collects all the input values and sends them as the POST body automatically.
<form hx-post="/submit-comment" hx-target="#comment-list" hx-swap="beforeend"> <input type="text" name="author" placeholder="Your name"> <textarea name="body" placeholder="Write your comment..."></textarea> <button type="submit">Post Comment</button> </form> <ul id="comment-list"> <li>First comment already here.</li> </ul>
Diagram:
User fills in name + comment, clicks "Post Comment"
|
v
HTMX collects form data:
author = "Alice"
body = "Great article!"
|
v
POST /submit-comment (data sent in request body)
|
v
Server saves comment, returns:
<li>Alice: Great article!</li>
|
v
HTMX appends the <li> to #comment-list
|
v
Page shows new comment at the bottom of the list — no reload
hx-post on a Button Inside a Form
When a button with hx-post sits inside a <form>, HTMX automatically includes all sibling input values in the POST body. This means you can trigger the submission from the button without putting hx-post on the form tag itself.
<form>
<input type="text" name="title" placeholder="Task title">
<button hx-post="/tasks" hx-target="#task-list" hx-swap="beforeend">
Add Task
</button>
</form>
<ul id="task-list"></ul>
Including Extra Data With hx-vals
You can attach extra data to any POST request using the hx-vals attribute. This is useful when you need to send additional context that is not in a form input.
<button
hx-post="/like"
hx-vals='{"post_id": 42}'
hx-target="#like-count">
Like
</button>
HTMX sends post_id=42 along with the POST request, even though there is no visible input field for it.
Real Example: Newsletter Sign-Up
<form hx-post="/subscribe" hx-target="#signup-message" hx-swap="outerHTML"> <input type="email" name="email" placeholder="Enter your email" required> <button type="submit">Subscribe</button> </form> <div id="signup-message"></div>
Server response on success:
<div id="signup-message"> <p>You are subscribed! Check your inbox.</p> </div>
Because hx-swap="outerHTML" replaces the entire target element (including the id), HTMX swaps out the old #signup-message div with the new one from the server — which now contains the confirmation text.
Server-Side Handling
Your server receives the POST data in the request body. Here is how each common framework reads it:
Flask (Python)
@app.route('/submit-comment', methods=['POST'])
def submit_comment():
author = request.form.get('author')
body = request.form.get('body')
# save to database...
return f'<li>{author}: {body}</li>'
Express (Node.js)
app.post('/submit-comment', (req, res) => {
const { author, body } = req.body;
// save to database...
res.send(`<li>${author}: ${body}</li>`);
});
Security: CSRF Protection
POST requests that modify server data require CSRF (Cross-Site Request Forgery) protection on most frameworks. To include a CSRF token with your HTMX POST, add the token as a hidden input inside your form:
<form hx-post="/save" hx-target="#result"> <input type="hidden" name="csrf_token" value="your-token-here"> <input type="text" name="title" placeholder="Title"> <button type="submit">Save</button> </form>
Alternatively, you can add the CSRF token to every HTMX request globally using a meta tag and a small JavaScript snippet, which the Security topic covers in detail.
Key Takeaway
The hx-post attribute sends data to the server when a user submits a form or clicks a button. HTMX automatically collects form input values and includes them in the POST body. The server saves the data and returns an HTML fragment confirming what happened. The page updates without a reload. Always include CSRF protection for any POST route that modifies server state.
