GET, POST, PUT y DELETE: los métodos HTTP explicados para principiantes

Cada vez que abres una página, envías un formulario o una aplicación habla con su servidor, se manda una petición HTTP. Toda petición lleva dos cosas: una dirección, que dice sobre qué se actúa, y un método, que dice qué hacer con ello. Los cuatro métodos que vas a usar casi siempre son GET, POST, PUT y DELETE. Esta guía los explica con esquemas y con ejemplos reales, sin dar nada por sabido.

Los cuatro, en una frase

MétodoQué haceEjemplo¿Lleva datos?Respuesta típica
GETLeer algo, sin cambiar nadaVer la lista de tareasNo200 OK con los datos
POSTCrear algo nuevo (o enviar datos para que el servidor los procese)Añadir una tarea, enviar un formularioSí201 Created
PUTReemplazar algo que ya existe, enteroCambiar la tarea 3 por su versión nuevaSí200 OK o 204 No Content
DELETEBorrar algoEliminar la tarea 3No204 No Content
Una forma de recordarlos. Son las cuatro operaciones básicas que se hacen con cualquier dato, las que en programación se conocen como CRUD: crear (POST), leer (GET), actualizar (PUT) y borrar (DELETE).

Cómo es una petición por dentro

Una petición HTTP es texto. La primera línea dice el método y la ruta; después vienen unas cabeceras con información extra; una línea en blanco marca el final, y detrás puede ir un cuerpo con datos. La respuesta tiene la misma forma, pero empieza con un código de estado que dice cómo fue.

Una petición y su respuesta, tal como viajan son líneas de texto: cambian el método, la ruta y el código, pero la forma es siempre esta PETICIÓN del cliente al servidor POST /tareas HTTP/1.1 método + ruta + versión Host: localhost:8000 cabeceras: información extra Content-Type: application/json (destino, formato, tamaño…) Content-Length: 31 línea en blanco: fin de cabeceras {"titulo": "Regar las plantas"} cuerpo: los datos (opcional) RESPUESTA del servidor al cliente HTTP/1.1 201 Created versión + código de estado Content-Type: application/json cabeceras Location: /tareas/4 (dónde quedó lo creado) línea en blanco {"id": 4, "titulo": "Regar las plantas", …} cuerpo: el resultado

Esquema: decodigo.com. La petición y la respuesta son las del ejemplo de POST de más abajo.

No hace falta creérselo: curl -v muestra lo que se envía (líneas con >) y lo que se recibe (con <):

curl -v http://localhost:8000/tareas/1
extracto de la salida: solo la petición y la respuesta> GET /tareas/1 HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.14.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: BaseHTTP/0.6 Python/3.13.16
< Date: Tue, 13 Oct 2026 15:52:47 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 50
<
{"id": 1, "titulo": "Comprar pan", "hecha": false}

Los cuatro métodos, con un ejemplo real

Para probarlos montamos una pequeña API: una lista de tareas en http://localhost:8000/tareas que empieza con dos. Usamos curl, que viene en Linux, macOS y Windows (desde Windows 10, en 2018); -i muestra también el código y las cabeceras de la respuesta, -X elige el método, -H añade una cabecera y -d manda datos en el cuerpo.

GET: leer

Pide algo y no cambia nada en el servidor. Es lo que hace el navegador cada vez que escribes una dirección o pulsas un enlace.

curl -i http://localhost:8000/tareas
salidaHTTP/1.1 200 OK
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:46 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 110

[{"id": 1, "titulo": "Comprar pan", "hecha": false}, {"id": 2, "titulo": "Llamar al dentista", "hecha": true}]

Si lo pedido no existe, el servidor no lo inventa: responde 404.

curl -i http://localhost:8000/tareas/9
salidaHTTP/1.1 404 Not Found
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 35

{"error": "no hay ninguna tarea 9"}

POST: crear

Envía datos en el cuerpo para crear algo nuevo. Se hace sobre la colección (/tareas), y es el servidor quien decide el número de la tarea nueva y lo dice en la cabecera Location. Content-Type avisa de que los datos van en JSON.

curl -i -X POST http://localhost:8000/tareas -H 'Content-Type: application/json' -d '{"titulo": "Pagar la luz"}'
salidaHTTP/1.1 201 Created
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Type: application/json; charset=utf-8
Location: /tareas/3
Content-Length: 51

{"id": 3, "titulo": "Pagar la luz", "hecha": false}

Si faltan datos, la culpa es de quien pide, y el código lo dice: 400 Bad Request.

curl -i -X POST http://localhost:8000/tareas -H 'Content-Type: application/json' -d '{}'
salidaHTTP/1.1 400 Bad Request
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 29

{"error": "falta el título"}

PUT: reemplazar

Manda la versión completa de algo que ya existe, y se hace sobre su dirección concreta (/tareas/3). Aquí marcamos la tarea como hecha; por eso se envían todos los campos, también el título que no cambia.

curl -i -X PUT http://localhost:8000/tareas/3 -H 'Content-Type: application/json' -d '{"titulo": "Pagar la luz", "hecha": true}'
salidaHTTP/1.1 200 OK
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 50

{"id": 3, "titulo": "Pagar la luz", "hecha": true}

Repetir exactamente el mismo PUT da la misma respuesta y deja la tarea igual: lo comprobamos ejecutándolo dos veces. Con POST no pasa: cada vez que se repite crea una tarea más.

DELETE: borrar

Borra lo que hay en esa dirección. No lleva cuerpo, y la respuesta tampoco suele llevarlo: 204 No Content significa «hecho, y no tengo nada que contarte».

curl -i -X DELETE http://localhost:8000/tareas/3
salidaHTTP/1.1 204 No Content
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Length: 0

Si se repite, ya no hay nada que borrar y la respuesta es 404. Aun así, el resultado en el servidor es el mismo: la tarea 3 no existe.

salida al repetirloHTTP/1.1 404 Not Found
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 35

{"error": "no hay ninguna tarea 3"}

Los cuatro métodos sobre la misma lista de tareas a la derecha, cómo queda la lista en el servidor después de cada petición GET GET /tareas leer · responde 200 OK #1 Comprar pan #2 Llamar al dentista POST POST /tareas crear · responde 201 Created #1 Comprar pan #2 Llamar al dentista #3 nueva Pagar la luz PUT PUT /tareas/3 reemplazar · responde 200 OK #1 Comprar pan #2 Llamar al dentista #3 cambiada Pagar la luz (hecha) DELETE DELETE /tareas/3 borrar · responde 204 No Content #1 Comprar pan #2 Llamar al dentista tarea 3 borrada

Esquema: decodigo.com, con las peticiones y los códigos de las pruebas anteriores.

¿Y PUSH? No existe: es PUT

Es una confusión muy común, porque push suena a «enviar» y se usa en Git (git push). Pero en HTTP no hay ningún método PUSH. Si lo envías, el servidor responde que no lo conoce:

curl -i -X PUSH http://localhost:8000/tareas
salida, con el cuerpo HTML recortadoHTTP/1.1 501 Unsupported method ('PUSH')
Server: BaseHTTP/0.6 Python/3.13.16
Date: Tue, 13 Oct 2026 15:52:47 GMT
Connection: close
Content-Type: text/html;charset=utf-8
Content-Length: 357
…
        <p>Message: Unsupported method ('PUSH').</p>
        <p>Error code explanation: 501 - Server does not support this operation.</p>
…

El código 501 Not Implemented es justo el que indica el estándar para un método que el servidor no reconoce. Hay otro método que sí verás a menudo: PATCH, que cambia solo una parte de algo (por ejemplo, solo "hecha": true), mientras que PUT lo reemplaza entero. Además existen HEAD (como GET, pero solo las cabeceras) y OPTIONS (qué métodos se permiten), menos frecuentes.

Seguro e idempotente: dos palabras que conviene conocer

  • Seguro: no cambia nada en el servidor. Se puede llamar sin miedo.
  • Idempotente: hacerlo una vez o diez da el mismo resultado final en el servidor. Si la conexión falla a medias, se puede repetir sin miedo a duplicar nada.
Método¿Seguro?¿Idempotente?Por qué
GETSíSíSolo lee
POSTNoNoRepetirlo crea otra tarea: así se duplican pedidos y pagos
PUTNoSíCambia datos, pero poner lo mismo dos veces deja lo mismo
DELETENoSíBorrar dos veces deja el mismo resultado: no está (aunque la respuesta cambie)

Por eso el navegador pregunta «¿Confirmar reenvío del formulario?» si recargas una página a la que llegaste con POST: sabe que repetirlo puede duplicar algo.

Los códigos de respuesta que más verás

El primer número dice el tipo de respuesta: 2xx, todo bien; 4xx, la petición tiene un problema (es culpa de quien pide); 5xx, el servidor ha fallado.

CódigoSignificaCuándo
200 OKTodo bien, aquí estáGET, PUT
201 CreatedCreadoPOST, con Location apuntando a lo nuevo
204 No ContentHecho, sin nada que devolverDELETE y a veces PUT
400 Bad RequestLa petición está mal formada o faltan datosUn POST sin título
401 UnauthorizedHay que identificarseFalta el usuario o la clave
403 ForbiddenTe conozco, pero no tienes permisoBorrar algo que no es tuyo
404 Not FoundEso no existeLa tarea 9
405 Method Not AllowedEl servidor conoce el método, pero no lo permite en esa direcciónUn DELETE sobre toda la colección
500 Internal Server ErrorEl servidor ha falladoUn error en su código
501 Not ImplementedEl servidor no conoce ese métodoPUSH

¿Y qué cambia con HTTPS?

Nada en lo que has visto: los métodos, las cabeceras y los códigos son exactamente los mismos. HTTPS es el mismo HTTP metido dentro de una conexión cifrada (TLS), normalmente en el puerto 443 en lugar del 80. Lo que cambia es quién puede verlo por el camino:

Quien mira el tráfico (el wifi, tu proveedor…)Con HTTPCon HTTPS
El método (GET, POST…)Lo veNo lo ve
La ruta y los parámetros (/tareas?buscar=luz)Lo veNo lo ve
Las cabeceras y el cuerpo (contraseñas, datos)Lo ve y puede cambiarloNo lo ve ni puede cambiarlo sin que se note
El dominio (decodigo.com)Lo veLo ve

Un detalle práctico: aunque con HTTPS la dirección completa viaja cifrada, no pongas contraseñas ni datos privados en la URL de un GET. Las direcciones se quedan en el historial del navegador y en los registros del servidor; esos datos van en el cuerpo de un POST. Si quieres ver cómo se cifra todo, paso a paso, está en la guía HTTPS por dentro.

Errores típicos al empezar

  • Usar GET para borrar o cambiar cosas (/borrar?id=3). Los navegadores, los buscadores y las vistas previas de enlaces hacen GET por su cuenta, porque se supone que es seguro, y podrían borrar algo sin que nadie lo pida.
  • Olvidar Content-Type al mandar JSON. Muchos servidores no sabrán leer el cuerpo y responderán 400 o 415.
  • Usar PUT para cambiar un solo campo. PUT reemplaza el recurso entero: lo que no envíes puede perderse. Para cambios parciales existe PATCH.
  • Esperar que un formulario HTML mande PUT o DELETE. El atributo method de un <form> solo acepta GET y POST; los otros se envían desde JavaScript (fetch) o con herramientas como curl.

Resumen

Quiero…MétodoDirecciónRespuesta si va bien
ver todas las tareasGET/tareas200 + la lista
ver una tareaGET/tareas/1200 + la tarea
crear una tareaPOST/tareas201 + Location
cambiar una tarea enteraPUT/tareas/3200 o 204
borrar una tareaDELETE/tareas/3204

Los ejemplos se ejecutaron el 13 de octubre de 2026 con curl 8.14.1 contra una API de prueba escrita con el módulo http.server de Python 3.13, en un contenedor desechable; las salidas están copiadas de esa ejecución. Los significados de los métodos y los códigos son los del estándar: RFC 9110 (semántica de HTTP) y, para PATCH, RFC 5789.

Fuente: IETF, RFC 9110, «HTTP Semantics», sección 9: Methods