Skip to main content
📄 HTML & the platform·Module A3 · Lesson 1
TaskBuild a login form: <form action='/api/login' method='post'> containing <input name='email' type='email'>, <input name='password' type='password'>, <button type='submit'>Log in</button>.

<form action method>: the request your backend receives

75 XP8 min
Theory

Three attributes shape the HTTP request

<form action="/api/signup" method="post" enctype="application/x-www-form-urlencoded">
  <input name="email" type="email" />
  <input name="password" type="password" />
  <button type="submit">Sign up</button>
</form>
  • `action` — where the form POSTs. Relative or absolute URL. Defaults to the current page.
  • `method`get (default, params in URL) or post (body). For mutations, use post. For searches, use get.
  • `enctype` — only matters for POST:

- application/x-www-form-urlencoded (default) — email=anna%40example.com&password=…

- multipart/form-data — required when one or more inputs are <input type="file">

- text/plain — never use this, it's only for debugging

What FastAPI sees

For <form method="post"><input name="email" value="anna@example.com"></form>, your FastAPI endpoint:

@app.post("/api/signup")
async def signup(email: str = Form()):
    return {"got": email}

The name="email" is the Pydantic field name. If you change name="user_email" on the input, FastAPI's Form(alias="user_email") is what catches it.

GET vs POST visibility

get puts data in the URL (/search?q=python) — bookmarkable, sharable, in browser history. post puts data in the body — invisible in URL, not in history, not bookmarked. Passwords ALWAYS POST.

🔒

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial — card required, cancel anytime.

Sign up — free trial →

First 15 lessons in each track are free. No card needed for those.

PreviousNext lesson →

Get one Python or web tip a day — by email

Short, hand-written, no spam. Unsubscribe in one click.