Pure JavaScript Send POST Data Without a Form
Asked Answered
H

13

310

Is there a way to send data using the POST method without a form and without refreshing the page using only pure JavaScript (not jQuery $.post())? Maybe httprequest or something else (just can't find it now)?

Haigh answered 18/6, 2011 at 12:46 Comment(2)
XMLHttpRequest is the answer ...$.post uses the same under the hood.Sacramentalism
This question can help you: [#58218410 [1]: #58218410Ables
D
305

You can send it and insert the data to the body:

var xhr = new XMLHttpRequest();
xhr.open("POST", yourUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: value
}));

By the way, for get request:

var xhr = new XMLHttpRequest();
// we defined the xhr

xhr.onreadystatechange = function () {
    if (this.readyState != 4) return;

    if (this.status == 200) {
        var data = JSON.parse(this.responseText);

        // we get the returned data
    }

    // end of state change: it can be after some time (async)
};

xhr.open('GET', yourUrl, true);
xhr.send();
Deadline answered 16/8, 2016 at 19:7 Comment(10)
What is the true boolean variable in xhr.open for?Endaendall
@Endaendall async: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/openDak
This is the old way of doing requests. I highly recommend not using this method and use fetch function instead.Edile
Here is a tutorial on this topic from the MDN pages: developer.mozilla.org/en-US/docs/Learn/Forms/…Hypocrite
@MichaelArtman Which is even today, more then a year after your comment not supported in all browsers.Endrin
@Endrin caniuse.com/fetch ~99% of the browser market share does have it.Edile
@MichaelArtman It says 95.96% market share on the exact page you linked which means 1 in 20 people will have a non-functional application.Endrin
@Endrin technically, it's closer to 1/25, and that one person knows they are using an older browser that most websites don't work with. Each year that percentage grows closer to 100%, so fetch is the correct choice.Edile
can you pls expand this answer to show code for handling success response and error response (or if its the same and we have to check the status code then that)Cadent
@MichaelArtman this answer is still very helpful for those of us cursed with writing web apps for government agencies, who are still inexplicably forcing their employees to only use IE even in 2023.Agenda
T
281

The Fetch API is intended to make GET requests easy, but it is able to POST as well.

let data = {element: "barium"};

fetch("/post/data/here", {
  method: "POST",
  headers: {'Content-Type': 'application/json'}, 
  body: JSON.stringify(data)
}).then(res => {
  console.log("Request complete! response:", res);
});

If you are as lazy as me (or just prefer a shortcut/helper):

window.post = function(url, data) {
  return fetch(url, {method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)});
}

// ...

post("post/data/here", {element: "osmium"});
Tenaculum answered 1/11, 2017 at 23:38 Comment(4)
Because of this answer's simplicity, I upvoted it prematurely and it doesn't allow me to retract my vote. Sending data only works if you add headers. (headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}) Furthermore, receiving data doesn't work either unless you call the json() method on the response, like this: res.json(), which happens to return yet another promise that you have to unwrap. Best to use async/await and unwrap all of these promises with await.Lucrative
fetch API is the current way to goTrace
Direct link to fetch function parameters documentation developer.mozilla.org/en-US/docs/Web/API/fetch#parametersResume
i used this technique. It somehow solved my problem but i went crazy when chrome developer's tool stopped showing response body. I thought it was an issue with my api. After hours of debugging, i got to know this is an issue with fetch api. Once you return res.json(), developer's tool started to show the response. I wish i had spent my friday night doing something more productive :(Aeon
C
70

You can use the XMLHttpRequest object as follows:

xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(someStuff);

That code would post someStuff to url. Just make sure that when you create your XMLHttpRequest object, it will be cross-browser compatible. There are endless examples out there of how to do that.

Climate answered 18/6, 2011 at 12:51 Comment(5)
could you write an example for someStuff?Bogan
someStuff = 'param1=val1&param2=val2&param3=val3'Townsley
That's a good answer, and someStuff can be anything you want even a simple string. you can check the request using online services such as my personal favorite: (requestb.in)Wensleydale
the application/x-www-form-urlencoded MIME type doesn't have a charset parameter: iana.org/assignments/media-types/application/…Lolalolande
the someStuff var would usually want to be set as "variable=value". Then you can retrieve the data with $_POST['variable'], this will be equal too the 'value'Bianchi
B
44

Also, RESTful lets you get data back from a POST request.

JS (put in static/hello.html to serve via Python):

<html><head><meta charset="utf-8"/></head><body>
Hello.

<script>

var xhr = new XMLHttpRequest();
xhr.open("POST", "/postman", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: 'value'
}));
xhr.onload = function() {
  console.log("HELLO")
  console.log(this.responseText);
  var data = JSON.parse(this.responseText);
  console.log(data);
}

</script></body></html>

Python server (for testing):

import time, threading, socket, SocketServer, BaseHTTPServer
import os, traceback, sys, json


log_lock           = threading.Lock()
log_next_thread_id = 0

# Local log functiondef


def Log(module, msg):
    with log_lock:
        thread = threading.current_thread().__name__
        msg    = "%s %s: %s" % (module, thread, msg)
        sys.stderr.write(msg + '\n')

def Log_Traceback():
    t   = traceback.format_exc().strip('\n').split('\n')
    if ', in ' in t[-3]:
        t[-3] = t[-3].replace(', in','\n***\n***  In') + '(...):'
        t[-2] += '\n***'
    err = '\n***  '.join(t[-3:]).replace('"','').replace(' File ', '')
    err = err.replace(', line',':')
    Log("Traceback", '\n'.join(t[:-3]) + '\n\n\n***\n*** ' + err + '\n***\n\n')

    os._exit(4)

def Set_Thread_Label(s):
    global log_next_thread_id
    with log_lock:
        threading.current_thread().__name__ = "%d%s" \
            % (log_next_thread_id, s)
        log_next_thread_id += 1


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_GET(self):
        Set_Thread_Label(self.path + "[get]")
        try:
            Log("HTTP", "PATH='%s'" % self.path)
            with open('static' + self.path) as f:
                data = f.read()
            Log("Static", "DATA='%s'" % data)
            self.send_response(200)
            self.send_header("Content-type", "text/html")
            self.end_headers()
            self.wfile.write(data)
        except:
            Log_Traceback()

    def do_POST(self):
        Set_Thread_Label(self.path + "[post]")
        try:
            length = int(self.headers.getheader('content-length'))
            req   = self.rfile.read(length)
            Log("HTTP", "PATH='%s'" % self.path)
            Log("URL", "request data = %s" % req)
            req = json.loads(req)
            response = {'req': req}
            response = json.dumps(response)
            Log("URL", "response data = %s" % response)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("content-length", str(len(response)))
            self.end_headers()
            self.wfile.write(response)
        except:
            Log_Traceback()


# Create ONE socket.
addr = ('', 8000)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
sock.listen(5)

# Launch 100 listener threads.
class Thread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i
        self.daemon = True
        self.start()
    def run(self):
        httpd = BaseHTTPServer.HTTPServer(addr, Handler, False)

        # Prevent the HTTP server from re-binding every handler.
        # https://stackoverflow.com/questions/46210672/
        httpd.socket = sock
        httpd.server_bind = self.server_close = lambda self: None

        httpd.serve_forever()
[Thread(i) for i in range(10)]
time.sleep(9e9)

Console log (chrome):

HELLO
hello.html:14 {"req": {"value": "value"}}
hello.html:16 
{req: {…}}
req
:
{value: "value"}
__proto__
:
Object

Console log (firefox):

GET 
http://XXXXX:8000/hello.html [HTTP/1.0 200 OK 0ms]
POST 
XHR 
http://XXXXX:8000/postman [HTTP/1.0 200 OK 0ms]
HELLO hello.html:13:3
{"req": {"value": "value"}} hello.html:14:3
Object { req: Object }

Console log (Edge):

HTML1300: Navigation occurred.
hello.html
HTML1527: DOCTYPE expected. Consider adding a valid HTML5 doctype: "<!DOCTYPE html>".
hello.html (1,1)
Current window: XXXXX/hello.html
HELLO
hello.html (13,3)
{"req": {"value": "value"}}
hello.html (14,3)
[object Object]
hello.html (16,3)
   {
      [functions]: ,
      __proto__: { },
      req: {
         [functions]: ,
         __proto__: { },
         value: "value"
      }
   }

Python log:

HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}
Breannebrear answered 17/9, 2017 at 23:7 Comment(0)
R
36

You can use XMLHttpRequest, fetch API, ...

If you want to use XMLHttpRequest you can do the following

var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    name: "Deska",
    email: "[email protected]",
    phone: "342234553"
 }));
xhr.onload = function() {
    var data = JSON.parse(this.responseText);
    console.log(data);
};

Or if you want to use fetch API

fetch(url, {
    method:"POST",
    body: JSON.stringify({
        name: "Deska",
        email: "[email protected]",
        phone: "342234553"
        })
    }).then(result => {
        // do something with the result
        console.log("Completed with result:", result);
    }).catch(err => {
        // if any error occured, then catch it here
        console.error(err);
    });
Ritter answered 12/4, 2020 at 5:16 Comment(0)
C
13

There is an easy method to wrap your data and send it to server as if you were sending an HTML form using POST. you can do that using FormData object as following:

data = new FormData()
data.set('Foo',1)
data.set('Bar','boo')

let request = new XMLHttpRequest();
request.open("POST", 'some_url/', true);
request.send(data)

now you can handle the data on the server-side just like the way you deal with reugular HTML Forms.

Additional Info

It is advised that you must not set Content-Type header when sending FormData since the browser will take care of that.

Cartwright answered 1/1, 2020 at 8:52 Comment(2)
❗️ FormData will create a multipart form request rather than an application/x-www-form-urlencoded requestAlgeciras
@Algeciras - thank you for clarification. since the OP did not mentioned which type of data is to be POST-ed, I think that FormData is most appropriate way to answer.Cartwright
P
12

Did you know that JavaScript has it's built-in methods and libs to create forms and submit them?

I am seeing a lot of replies here all asking to use a 3rd party library which I think is an overkill.

I would do the following in pure Javascript:

<script>
function launchMyForm()
{
   var myForm = document.createElement("FORM");
   myForm.setAttribute("id","TestForm");
   document.body.appendChild(myForm);

// this will create a new FORM which is mapped to the Java Object of myForm, with an id of TestForm. Equivalent to: <form id="TestForm"></form>

   var myInput = document.createElement("INPUT");
   myInput.setAttribute("id","MyInput");
   myInput.setAttribute("type","text");
   myInput.setAttribute("value","Heider");
   document.getElementById("TestForm").appendChild(myInput);
   
// To submit the form: 
   myForm.method = "POST";
   myForm.action = "whatever.aspx";  // or "response.php" 
   myForm.submit();

// This will create an INPUT equivalent to: <INPUT id="MyInput" type="text" value="Heider" /> and then assign it to be inside the TestForm tags. 
}
</script>

This way (A) you don't need to rely on 3rd parties to do the job. (B) It's all built-in to all browsers, (C) faster, (D) it works, feel free to try it out.

I hope this helps.

H

Palinode answered 25/5, 2020 at 23:17 Comment(2)
I like this reply. Now you've created a form, but how do you send it, though?Breve
Hello, I looked at my reply and you are absolutely right, just revised it and added how to submit, hope all goes well, give me a shout I you need more help, cheers, Heider.Palinode
R
8

navigator.sendBeacon()

If you simply need to POST data and do not require a response from the server, the shortest solution would be to use navigator.sendBeacon():

const data = JSON.stringify({
  example_1: 123,
  example_2: 'Hello, world!',
});

navigator.sendBeacon('example.php', data);
Rivera answered 21/3, 2019 at 1:39 Comment(2)
Failed to execute 'sendBeacon' on 'Navigator': Beacons are only supported over HTTP(S).Jacklynjackman
navigator.sendBeacon is not meant to be used for this purpose in my opinion.Crossgrained
L
7

The most popular answers here do not show how to get data back from the POST. Also, the popular "fetch" solutions do not work in the latest version of Chrome when sending data to the latest version of NodeJS unless you pass headers and also unwrap the response.json() promise. Also, the popular answers do not use async/await.

Here is the cleanest and most complete solution I could come up with that works.

async function postJsonData(jsonObject) {
    const response = await fetch("/echo", {
        method: "POST",
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(jsonObject)
    });
    
    const actualResponse = await response.json();
}
Lucrative answered 2/6, 2021 at 4:5 Comment(1)
Nice. If somebody wants to use that solution within node.js, read this: #48434283Vernitavernoleninsk
T
4
const data = { username: 'example' };

fetch('https://example.com/profile', {
  method: 'POST', // or 'PUT'
  headers: {
 '           Content-Type': 'application/json',
           },
  body: JSON.stringify(data),
})
  .then(response => response.json())
  .then(data => {
      console.log('Success:', data);
     })
 .catch((error) => {
         console.error('Error:', error);
   });
Tartar answered 23/1, 2021 at 6:35 Comment(1)
"Invalid Name Error"Antiicer
V
4

Here is a nice function you (or anyone else) could use in their code:

function post(url, data) {
    return new Promise((res, rej) => {
        let stringified = "";
        for (const [key, value] of Object.entries(data))
            stringified += `${stringified != '' ? '&' : ''}${key}=${value}`

        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState == 4)
                if (xhr.status == 200)
                    res(xhr.responseText)
                else
                    rej({ code: xhr.status, text: xhr.responseText })
        }
        xhr.open("POST", url, true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(stringified);
    })
}
Valaree answered 25/7, 2021 at 14:52 Comment(5)
res and rej are not defined.Gismo
@Matt, Please clarify what you mean by that. Is that an error that you're getting?Valaree
res and rej are defined on line 2.Valaree
what does res do? If I wanted to pass the response in json format to a function, there where do I put it in this code?Cadent
if you want the function to return something else, change what is being passed to resValaree
W
0

You can also use this: https://github.com/floscodes/JS/blob/master/Requests.js

You can easily send a http-Request. Just use:

HttpRequest("https://example.com", method="post", data="yourkey=yourdata");

That's it! It should even work if the site is CSRF-protected.

Or just send a GET-Request by using

HttpRequest("https://example.com", method="get");
Walczak answered 7/6, 2021 at 9:24 Comment(0)
H
0

use this func of jbezz library

var makeHttpObject = function () {
  try {return new XMLHttpRequest();}
  catch (error) {}
  try {return new ActiveXObject("Msxml2.XMLHTTP");}
  catch (error) {}
  try {return new ActiveXObject("Microsoft.XMLHTTP");}
  catch (error) {}
  throw new Error("Could not create HTTP request object.");
}
function SendData(data){
    let type = (data.type ? data.type : "GET")
    let DataS = data.data;
    let url = data.url;
    let func = (data.success ? data.success : function(){})
    let funcE =(data.error ? data.error : function(){})
    let a_syne = (data.asyne ? data.asyne : false); 
    let u = null;
    try{u = new URLSearchParams(DataS).toString();}catch(e){u = Object.keys(DataS).map(function(k) {return encodeURIComponent(k) + '=' + encodeURIComponent(DataS[k])}).join('&')}
    if(type == "GET"){url +="?"+u}
    const xhttp =  makeHttpObject();
    xhttp.onload = function(){func(this.responseText)}
    xmlHttp.onreadystatechange = function() {if (xmlHttp.readyState == 4) 
    {if(xmlHttp.status !== 200){funcE(xmlHttp.statusText)}}}
    xhttp.open(type,url,a_syne);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(u);
}

use this to run :

SendData({
    url:"YOUR_URL",
    asyne:true,
    type:"POST", // or GET
    data:{
        username:"ali",
        password:"mypass" // Your Data
    },
    success:function(Result){
        console.log(Result)
    },
    error:function(e){
        console.log("We Have Some Error")
    }
});

Or

download jbezz and add to your page.

download link : github.com

use :

$$.api({
        url:"YOUR_URL",
        asyne:true,
        type:"POST", // or GET
        data:{
            username:"ali",
            password:"mypass" // Your Data
        },
        success:function(Result){
            console.log(Result)
        },
        error:function(e){
            console.log("We Have Some Error")
        }
    });
Highbinder answered 19/9, 2021 at 13:3 Comment(1)
@José i do my best.Highbinder

© 2022 - 2024 — McMap. All rights reserved.