HTMX Your First Request
You have HTMX installed. Now you write your first working HTMX interaction. This topic walks you through a complete, working example step by step. By the end, you will have a button that fetches content from a server and places it on the page — with zero custom JavaScript.
The Goal
Build a page with a button. When the user clicks that button, HTMX sends a request to the server, gets back a short piece of HTML, and displays it below the button. No page reload happens.
BEFORE click: ┌──────────────────────────┐ │ [ Click Me ] │ └──────────────────────────┘ AFTER click: ┌──────────────────────────┐ │ [ Click Me ] │ │ │ │ Hello from the server! │ └──────────────────────────┘
Step 1: The HTML Page
Create a file called index.html with this content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>First HTMX Request</title>
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
</head>
<body>
<button
hx-get="/greeting"
hx-target="#result"
hx-swap="innerHTML">
Click Me
</button>
<div id="result"></div>
</body>
</html>
Breaking Down the Attributes
| Attribute | Value | What It Does |
|---|---|---|
| hx-get | /greeting | Sends a GET request to the /greeting URL when clicked |
| hx-target | #result | Tells HTMX to put the response into the div with id="result" |
| hx-swap | innerHTML | Replaces the inner content of the target div with the response |
Step 2: The Server Response
Your server needs a route at /greeting that returns an HTML fragment. Here is what that looks like in three common server languages:
Python (Flask)
from flask import Flask
app = Flask(__name__)
@app.route('/greeting')
def greeting():
return '<p>Hello from the server!</p>'
Node.js (Express)
const express = require('express');
const app = express();
app.get('/greeting', (req, res) => {
res.send('<p>Hello from the server!</p>');
});
PHP
<?php // File: greeting.php echo '<p>Hello from the server!</p>';
All three servers do the same thing: they send back a small piece of HTML. HTMX places that HTML inside the #result div.
Step 3: The Full Flow Visualized
User clicks [ Click Me ]
|
v
HTMX reads: hx-get="/greeting"
|
v
HTMX sends: GET /greeting ------> Server
|
Server runs code
|
Returns: <p>Hello from the server!</p>
| |
<------- HTMX receives the response
|
v
HTMX reads: hx-target="#result", hx-swap="innerHTML"
|
v
HTMX writes <p>Hello from the server!</p> into <div id="result">
|
v
Page shows "Hello from the server!" — no reload
What You Did Not Need to Write
Notice what is missing from the page. You wrote no addEventListener, no fetch() call, no document.getElementById(), and no innerHTML assignment. HTMX handled every one of those steps automatically by reading your HTML attributes.
Testing Without a Server
If you open an HTML file directly from your file system (with a file:// URL), HTMX cannot send HTTP requests because there is no server to receive them. You need a local development server.
The easiest option is Python's built-in server. Open your terminal in the project folder and run:
python -m http.server 8000
Then open http://localhost:8000 in your browser. Note that this simple server only serves static files — it cannot handle the /greeting route. For a full round-trip test, use Flask, Express, or any server-side framework.
What Happens on Error
If the server returns a 404 or 500 status, HTMX does not crash the page. It fires an internal event called htmx:responseError. You can listen for that event later to show a friendly error message. For now, just know that HTMX fails gracefully.
Experiment: Change the Trigger
By default, HTMX triggers a button's request on a click. Try adding hx-trigger="mouseover" to fire the request when the mouse hovers over the button instead:
<button hx-get="/greeting" hx-target="#result" hx-swap="innerHTML" hx-trigger="mouseover"> Hover Over Me </button>
This tiny change shows you how flexible HTMX is. The same three core attributes — hx-get, hx-target, hx-swap — stay the same. Only the trigger changes.
Key Takeaway
Your first HTMX request needs just three attributes on a button: hx-get to set the URL, hx-target to pick where the response lands, and hx-swap to decide how it replaces content. The server returns a plain HTML fragment. HTMX handles everything in between. This is the foundation every other topic in this course builds on.
