Олег Марков
Атрибут method в HTML - как правильно отправлять данные формы
Введение
Атрибут method в HTML отвечает за то, как браузер отправит данные формы на сервер. От выбора значения этого атрибута зависит:
- куда попадут данные – в URL или в тело запроса
- какие ограничения по размеру будут у отправляемых данных
- как сервер сможет эти данные прочитать
- как поведут себя кэширование, история браузера и закладки
- какие риски безопасности появятся
Если вы работаете с веб-формами, то атрибут method – один из ключевых инструментов. Смотрите, я покажу вам, как он устроен, какие значения поддерживает HTML, чем отличаются GET и POST на практике, и как избежать типичных ошибок при выборе метода.
Что такое атрибут method в HTML
Базовое определение
Атрибут method задается у тега формы:
<form action="/search" method="get">
<!-- Поля формы -->
</form>Основная идея:
- тег
<form>описывает структуру данных, которые вы хотите отправить - атрибут action указывает, куда отправить данные (URL)
- атрибут method говорит, как отправить данные (HTTP-метод запроса)
Если вы не зададите method явно, браузер будет вести себя так, как описано в спецификации: для тегов <form> по умолчанию используется метод GET.
Поддерживаемые значения method
На практике чаще всего вы используете:
- GET
- POST
Но HTML также позволяет указать:
- dialog
- а также другие HTTP-методы (PUT, DELETE, PATCH и т.д.) через HTML5, хотя их реальная поддержка браузерами и серверной логикой ограничена и используется редко.
Давайте разберемся с основными методами подробнее.
Метод GET
Как работает GET для формы
Когда вы указываете method="get", данные формы кодируются в строку запроса и добавляются к URL после символа ?.
Пример:
<form action="/search" method="get">
<!-- Поле для строки поиска -->
<input type="text" name="q" />
<!-- Кнопка отправки формы -->
<button type="submit">Найти</button>
</form>Если пользователь введет в поле значение:
- q = html method
то браузер отправит запрос примерно такого вида:
GET /search?q=html+method HTTP/1.1
Host: example.comКомментарии:
- строка
?q=html+method– это параметры запроса - пробелы кодируются в
+или%20 - любые спецсимволы в значениях полей формы будут URL-кодированы
Где хранится тело данных при GET
При GET нет тела запроса с данными формы. Весь набор полей попадает:
- в URL (query string)
- в логи сервера (где логируется вся строка запроса)
- в историю браузера
- в адресную строку, которую легко скопировать, переслать или добавить в закладки
Поэтому GET очень удобен, когда данные:
- не чувствительные
- небольшие по объему
- описывают "запрос" к ресурсу, а не изменение данных
Когда использовать GET
Давайте перечислим типичные случаи, когда method="get" – это правильный выбор:
Поисковые формы
- строка поиска
- фильтрация товаров, статей, пользователей
- сортировка и пагинация
Пример:
<form action="/products" method="get"> <!-- Фильтр по категории --> <select name="category"> <option value="">Все</option> <option value="phones">Телефоны</option> <option value="laptops">Ноутбуки</option> </select> <!-- Фильтр по минимальной цене --> <input type="number" name="price_min" placeholder="От" /> <!-- Кнопка применения фильтра --> <button type="submit">Фильтровать</button> </form>Здесь вы легко можете поделиться ссылкой:
/products?category=phones&price_min=10000.Операции чтения (идемпотентные запросы)
GET подходит, когда:
- вы не изменяете данные на сервере
- повторный запрос не меняет результат (например, просмотр профиля, просмотр списка товаров, поиск)
Страницы, которые нужно кэшировать
Браузеры и прокси могут кэшировать результаты GET-запросов. Это улучшает производительность при:
- переходах назад-вперед
- повторных поисках
- одинаковых фильтрах
Ограничения метода GET
Теперь давайте аккуратно разберем ограничения.
Ограничение длины URL
Каждый браузер и сервер накладывает ограничение на длину URL. Жесткого стандарта нет, но:
- на практике стоит считать безопасной длиной до 2000–4000 символов
- для сложных форм с массивами данных GET становится непрактичным
Смотрите, к чему это ведет:
- большие текстовые поля (комментарии, описания) через GET передавать нельзя
- вложенные структуры, длинные JSON-строки – тоже плохая идея
Проблемы с безопасностью
Основная проблема GET – данные видны в:
- адресной строке
- истории браузера
- логах сервера и промежуточных прокси
- сервисах аналитики (если URL туда попадают)
Поэтому через GET запрещено передавать:
- пароли
- токены аутентификации
- персональные данные (паспортные данные, номера карт и т.п.)
- любые чувствительные значения
Кэширование и повтор запросов
GET-запросы могут кэшироваться:
- браузером
- прокси
- CDN
Это удобно для поиска или фильтрации, но:
- повторный запрос GET может не дойти до сервера
- пользователь при нажатии "Назад" может увидеть кэшированный результат
- промежуточные узлы видят все параметры в URL
Обработка GET на сервере
Форматы зависят от языка, но общая идея одна – данные формы при GET попадают в набор параметров строки запроса.
Давайте посмотрим пример на PHP:
<?php
// Получаем значение поля q из параметров GET
$search = $_GET['q'] ?? ''; // Если параметр не передан, используем пустую строку
?>И пример на Node.js (Express):
// Обрабатываем GET-запрос на /search
app.get('/search', (req, res) => {
// Получаем параметр q из строки запроса
const search = req.query.q || ''; // Если q нет - берем пустую строку
// Дальше выполняем поиск и отправляем результат
res.send(`Результаты поиска для: ${search}`);
});Метод POST
Как работает POST для формы
Когда вы указываете method="post", данные формы отправляются в теле HTTP-запроса, а не в URL.
Пример:
<form action="/login" method="post">
<!-- Поле для логина -->
<input type="text" name="username" />
<!-- Поле для пароля -->
<input type="password" name="password" />
<!-- Кнопка входа -->
<button type="submit">Войти</button>
</form>Запрос будет выглядеть примерно так:
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=admin&password=secret123Комментарии:
- данные скрыты из строки URL, но не зашифрованы сами по себе
- важно использовать HTTPS, чтобы скрыть содержимое тела запроса от перехвата в сети
Когда использовать POST
Давайте сформируем четкие критерии:
Запросы, изменяющие данные на сервере
Используйте POST для:
- регистрации пользователей
- изменения профиля
- добавления или удаления записей
- оформления заказа
- всех операций, которые что-то меняют в базе или на сервере
Передача чувствительных данных
Только в сочетании с HTTPS, но все равно:
- пароли
- токены
- конфиденциальные поля
- большие текстовые сообщения
Большие объемы данных
POST позволяет отправить:
- большие формы
- длинные тексты
- файлы (в сочетании с enctype="multipart/form-data")
Здесь как раз нет строгого ограничения длины, как у URL, но сервер может иметь собственные лимиты на размер тела запроса.
Отличия POST от GET с точки зрения HTTP
Давайте систематизируем:
Где хранятся данные
- GET – в URL (строка запроса)
- POST – в теле запроса
Максимальный размер
- GET – ограничен длиной URL
- POST – ограничен настройками сервера (обычно заметно выше)
Кэширование
- GET – может кэшироваться
- POST – обычно не кэшируется
Повторяемость
- GET – запрос может безопасно повторяться (если вы не сломали идею HTTP)
- POST – может приводить к повторному созданию/изменению ресурсов (например, двойная отправка заказа)
История браузера
- GET – параметры сохраняются в истории
- POST – повторная отправка через форму подтверждения ("Повторно отправить данные формы?")
Примеры использования POST
Давайте посмотрим, как POST применяют в реальных задачах.
Регистрация пользователя
<form action="/signup" method="post">
<!-- Имя пользователя -->
<input type="text" name="username" required />
<!-- Email пользователя -->
<input type="email" name="email" required />
<!-- Пароль -->
<input type="password" name="password" required />
<!-- Кнопка регистрации -->
<button type="submit">Зарегистрироваться</button>
</form>Комментарии:
- здесь нельзя использовать GET, так как пароль окажется в URL
- данные регистрации изменяют состояние системы (создают пользователя)
Загрузка файла
<form action="/upload" method="post" enctype="multipart/form-data">
<!-- Поле для выбора файла -->
<input type="file" name="file" />
<!-- Кнопка отправки файла -->
<button type="submit">Загрузить</button>
</form>Комментарии:
- здесь используется POST, так как только он позволяет корректно передать бинарные данные файлов
- атрибут enctype управляет форматом кодирования тела запроса
- GET в сочетании с файлами не работает
Обработка POST на сервере
Механика зависит от языка, но общая схема:
- данные берутся из тела запроса
- их нужно распарсить в зависимости от
Content-Type
Пример на PHP:
<?php
// Получаем данные формы из POST
$username = $_POST['username'] ?? ''; // Логин
$password = $_POST['password'] ?? ''; // Пароль
// Здесь можно провести аутентификацию пользователя
?>Пример на Node.js (Express, с использованием body-parser / встроенного парсера):
// Включаем парсер urlencoded-данных форм
app.use(express.urlencoded({ extended: false }));
// Обрабатываем POST-запрос на /login
app.post('/login', (req, res) => {
// Получаем поля формы из тела запроса
const username = req.body.username; // Логин
const password = req.body.password; // Пароль
// Здесь выполняем проверку логина и пароля
res.send('Обработка входа');
});Другие значения атрибута method
Значение dialog
HTML5 ввел элемент <dialog> и метод submit для форм, встроенных в диалог.
Атрибут method может принимать значение dialog:
<dialog id="myDialog">
<form method="dialog">
<!-- Поле ввода имени -->
<input name="username" />
<!-- Кнопка подтверждения -->
<button value="ok">Ок</button>
<!-- Кнопка отмены -->
<button value="cancel">Отмена</button>
</form>
</dialog>Как это работает:
- такая форма не отправляет данные на сервер
- она просто "закрывает" диалог
- значение кнопки (
value) можно прочитать в JavaScript как результат диалога
Пример JavaScript-кода:
// Находим диалог по id
const dialog = document.getElementById('myDialog');
// Открываем диалог
dialog.showModal();
// Слушаем событие закрытия
dialog.addEventListener('close', () => {
// Значение возврата (value у нажатой кнопки)
const result = dialog.returnValue; // ok или cancel
// Здесь можно обработать результат
});Комментарии:
- method="dialog" не относится к HTTP-методам
- он используется только для внутренней логики диалога в браузере
- запрос на сервер при этом не отправляется
Другие HTTP-методы (PUT, DELETE и т.д.)
Спецификация HTML разрешает указывать в method не только GET/POST, но и:
- PUT
- DELETE
- PATCH
- другие строковые значения
Но давайте посмотрим на практику:
- большинство браузеров технически разрешат отправить такие запросы
- многие серверные фреймворки не принимают данные форм с такими методами "из коробки"
- старые браузеры и промежуточные прокси могут вести себя нестандартно
Поэтому распространен подход:
- использовать method="post"
- указывать "настоящий" метод в скрытом поле, например:
<form action="/users/1" method="post">
<!-- Скрытое поле для указания "логического" метода -->
<input type="hidden" name="_method" value="put" />
<!-- Поля формы для редактирования -->
<input name="name" />
<button type="submit">Сохранить</button>
</form>А на сервере:
- читать поле
_method - трактовать запрос как PUT, DELETE и т.п.
Этот прием часто используется в фреймворках вроде Laravel, Ruby on Rails, некоторых Node.js-фреймворках.
Взаимодействие method с другими атрибутами формы
method и action
Атрибут action задает URL, на который отправляется форма. Атрибут method – HTTP-метод.
Пример комбинации:
<form action="/api/users" method="post">
<!-- Поле для имени -->
<input type="text" name="name" />
<!-- Поле для email -->
<input type="email" name="email" />
<!-- Кнопка отправки -->
<button type="submit">Создать пользователя</button>
</form>Комментарии:
- если action не указан, форма отправляется на текущий URL страницы
- если method не указан, используется GET
method и enctype
Атрибут enctype задает формат кодирования тела запроса. Он имеет смысл только для method="post" (и других методов с телом запроса).
Основные значения:
application/x-www-form-urlencoded(по умолчанию)- поля формы кодируются в формате
key=value&key2=value2 - используются для обычных форм без файлов
- поля формы кодируются в формате
multipart/form-data- используется для отправки файлов
- каждое поле и файл передаются как отдельная "часть" (boundary)
- обязателен при type="file"
text/plain- редко используется
- данных кодируются "как есть" в текстовом виде
- почти всегда лучше оставить
application/x-www-form-urlencoded
Пример с enctype:
<form action="/profile" method="post" enctype="multipart/form-data">
<!-- Имя пользователя -->
<input type="text" name="name" />
<!-- Аватар -->
<input type="file" name="avatar" />
<!-- Кнопка сохранения -->
<button type="submit">Сохранить</button>
</form>Комментарии:
- если вы попытаетесь отправить файл без multipart/form-data – сервер его не получит корректно
- для GET атрибут enctype игнорируется
method и атрибут formmethod у кнопок
Иногда нужно, чтобы одна и та же форма отправлялась разными методами в зависимости от кнопки. Для этого HTML предоставляет атрибут formmethod на элементах:
<button><input type="submit">
Смотрите, я покажу вам пример:
<form action="/items" method="post">
<!-- Поле для названия товара -->
<input type="text" name="title" />
<!-- Кнопка отправки с методом POST (как у формы) -->
<button type="submit">Сохранить (POST)</button>
<!-- Кнопка отправки с методом GET -->
<button type="submit" formmethod="get">Предпросмотр (GET)</button>
</form>Как это работает:
- первая кнопка использует метод, указанный в форме – POST
- вторая кнопка переопределяет метод на GET только для этого нажатия
Комментарии:
- formmethod всегда имеет приоритет над method формы
- это удобно для "предпросмотра", "поиска" или вспомогательных действий
Как браузер кодирует данные формы в зависимости от method
GET и кодирование query string
Когда вы отправляете форму с method="get":
- Браузер берет все элементы с атрибутом name и подходящими типами
- Формирует пары имя–значение
- Применяет URL-кодирование:
- пробелы, спецсимволы кодируются в
%XX
- пробелы, спецсимволы кодируются в
- Склеивает пары через
& - Добавляет результат к URL после
?
Пример:
поля:
- name = Иван
- city = Москва
результат в URL (в виде, близком к реальному):
/search?name=%D0%98%D0%B2%D0%B0%D0%BD&city=%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0
POST и кодирование тела запроса
Здесь многое зависит от enctype. Давайте разберем два основных случая.
application/x-www-form-urlencoded
Алгоритм почти такой же, как при GET, только результат помещается в тело запроса:
POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=admin&password=secretКомментарии:
- это формат по умолчанию
- большинство серверных фреймворков "из коробки" умеют его разбирать
multipart/form-data
Этот формат сложнее. Структура тела запроса примерно такая:
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryabc123
------WebKitFormBoundaryabc123
Content-Disposition: form-data; name="title"
Мой файл
------WebKitFormBoundaryabc123
Content-Disposition: form-data; name="file"; filename="photo.jpg"
Content-Type: image/jpeg
...здесь бинарное содержимое файла...
------WebKitFormBoundaryabc123--Комментарии:
- каждая часть отделяется строкой с boundary
- поля формы и файлы становятся отдельными "секциями"
- такой формат нужен именно для файлов и сложных структур
Рекомендации по выбору значения method
Базовые правила выбора
Давайте сформулируем простую схему:
- Если запрос читающий (получение данных, поиск, фильтр) – GET
- Если запрос изменяет данные (создание, обновление, удаление) – POST
- Если есть чувствительные данные – POST + HTTPS
- Если есть файлы – POST + enctype="multipart/form-data"
- Если нужна ссылка, которой можно поделиться – GET
Типичные примеры из практики
- Форма поиска по сайту – GET
- Фильтр каталога товаров – GET
- Вход в аккаунт – POST
- Регистрация – POST
- Оформление заказа – POST
- Обновление настроек профиля – POST
- Предпросмотр контента (без сохранения) – чаще всего GET, иногда POST (если данные слишком большие)
Частые ошибки при использовании method
Давайте посмотрим на распространенные ситуации.
1. Использование GET для формы входа
<!-- Так делать не нужно -->
<form action="/login" method="get">
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">Войти</button>
</form>Проблема:
- пароль окажется в URL
- он попадет в историю, логи, может утечь в реферере
Как исправить:
<form action="/login" method="post">
<!-- Логин -->
<input type="text" name="username" />
<!-- Пароль -->
<input type="password" name="password" />
<!-- Кнопка входа -->
<button type="submit">Войти</button>
</form>И обязательно использовать HTTPS на стороне сервера.
2. Отправка больших текстов через GET
<!-- Так делать не стоит -->
<form action="/preview" method="get">
<!-- Большое текстовое поле -->
<textarea name="content"></textarea>
<button type="submit">Предпросмотр</button>
</form>Проблема:
- контент может не поместиться в URL
- возникнут ошибки "URI too long"
Лучше:
<form action="/preview" method="post">
<!-- Большой текст отправляем через POST -->
<textarea name="content"></textarea>
<button type="submit">Предпросмотр</button>
</form>3. Игнорирование семантики HTTP
Иногда разработчики используют POST всегда, "на всякий случай". Это:
- ломает кэширование
- делает ссылки на поисковые запросы неудобными
- ухудшает совместимость с некоторыми клиентами
Поддерживайте различие между:
- безопасными, идемпотентными операциями (GET)
- изменяющими состояние операциями (POST)
Взаимодействие с JavaScript и AJAX
Хотя атрибут method относится к HTML-формам, он часто используется совместно с JavaScript.
Использование method при отправке через fetch
Даже если вы отправляете форму через JavaScript, имеет смысл:
- читать method из формы
- использовать его в запросе
Пример:
<form id="userForm" action="/api/users" method="post">
<!-- Поле для имени -->
<input type="text" name="name" />
<!-- Поле для email -->
<input type="email" name="email" />
<!-- Кнопка отправки -->
<button type="submit">Сохранить</button>
</form>
<script>
// Находим форму
const form = document.getElementById('userForm');
form.addEventListener('submit', async (event) => {
// Отменяем стандартную отправку
event.preventDefault();
// Берем URL и метод из атрибутов формы
const url = form.action; // /api/users
const method = form.method; // post
// Собираем данные формы
const formData = new FormData(form); // Собирает все поля name=value
// Отправляем запрос с тем же методом, что у формы
const response = await fetch(url, {
method: method, // Используем значение из атрибута method
body: formData // Отправляем данные формы
});
// Обрабатываем ответ
const result = await response.json();
// Здесь можно обновить интерфейс
});
</script>Здесь вы видите, как метод формы определяет HTTP-метод запроса даже при кастомной отправке.
Проверка и изменение method через JavaScript
Иногда нужно динамически менять метод отправки. Это не всегда хорошая идея, но технически возможно.
Пример:
// Находим форму
const form = document.querySelector('form');
// Меняем метод на POST в зависимости от условия
if (shouldUsePost()) {
form.method = 'post'; // Меняем атрибут method у формы
}Комментарии:
form.method– свойство DOM-объекта, которое синхронизируется с атрибутом в HTML- такое изменение влияет на дальнейшую отправку формы
Заключение
Атрибут method в HTML определяет способ отправки данных формы и напрямую влияет на:
- безопасность (видны ли данные в URL)
- объем передаваемой информации
- кэширование и работу истории браузера
- семантику HTTP и обработку запросов на сервере
Основные практические выводы:
- используйте GET для чтения данных, поиска и фильтров
- используйте POST для изменения данных, регистрации, авторизации и любых чувствительных операций
- передавайте файлы только через POST в сочетании с multipart/form-data
- избегайте передачи паролей и персональных данных через GET
- корректно используйте formmethod у кнопок, если нужно временно переопределять метод
Если вы будете осознанно выбирать значение method, ваши формы станут:
- безопаснее
- предсказуемее в поведении
- проще в поддержке на стороне сервера
Частозадаваемые технические вопросы по теме атрибута method в HTML
Можно ли отправить JSON из обычной HTML-формы с методом POST
Да, но стандартная форма не умеет сама создавать JSON. Обычно делают так
- Вешаете обработчик submit на форму
- Собираете данные в объект
- Сериализуете в JSON и отправляете через fetch с
Content-Type: application/json
Стандартная отправка формы (без JS) всегда кодирует данные какapplication/x-www-form-urlencodedилиmultipart/form-data.
Почему сервер не видит данные при методе POST хотя форма отправляется
Частая причина – отсутствие корректного парсера тела запроса на сервере. Проверьте
- Установлен ли парсер urlencoded или multipart (в зависимости от enctype)
- Совпадает ли ожидаемый метод маршрута на сервере (например,
app.post(...)) с method формы - Не превышен ли лимит размера тела запроса в настройках сервера.
Можно ли использовать method="put" или method="delete" без JavaScript
Технически да – браузер отправит такой запрос. Но
- Многие серверы и фреймворки по умолчанию не принимают формы с этими методами
- Промежуточные прокси могут вести себя нестандартно
На практике чаще используют POST плюс скрытое поле_method, а "настоящий" метод эмулируют на сервере.
Как запретить браузеру повторно отправлять POST при обновлении страницы
Полностью запретить нельзя – это стандартное поведение. Рекомендуемый подход – шаблон Post Redirect Get
- Принимаете POST на сервере
- Обрабатываете данные
- Возвращаете ответ с перенаправлением (status 302/303) на страницу результата
- Пользователь видит результат по GET и обновление страницы не вызывает повторный POST.
Почему при методе GET нажатие Back в браузере сразу показывает старые результаты
Браузер кэширует результат GET-запроса и часто восстанавливает страницу из истории без нового запроса. Если это нежелательно
- Настройте HTTP-заголовки Cache-Control и Pragma на стороне сервера
- При необходимости добавляйте в URL временные метки или другие параметры, чтобы делать запросы уникальными и контролировать кэширование.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев