Cross-Domain POST With JavaScript
Normally you can’t send cross-domain requests in JavaScript due to restrictions imposed by the same-origin security policy. There are many clever hacks that circumvent this by using remote script includes (even CSS includes) or proxy scripts, but so far I haven’t seen anything useful for client-side, cross-domain POST requests.
However, it turns out you can send them very easily if you don’t need to know the response to the request. This might sound useless at first, but there are certain situations where it’s all you really need. For example, blackhat SEO comes to mind…
The Basic Idea
Forms can use the POST method and JS can submit forms. This means you can dynamically generate a form with the action attribute set to any URL (including pages on other domains) and encode all query parameters as hidden <input> fields, then automatically submit the form.
The problem is this works exactly as if the user had filled out a form and clicked “Submit” - the browser will send the request and open a different page. That’s (usually) bad, so we need to put the form inside an invisible iframe to hide the redirect. Of course, you can’t get any response data from the frame, so it’s truly “fire and forget”.
As a result, the final script will have two components - a JavaScript function that creates the iframe, and another script that will run inside the frame and generate and submit the form.
Implementing It
The first part is the crossDomainPost() JS function. This is the function you will call from your script to initiate a POST request. The function accepts three arguments :
- writer_url - the URL of the script that will generate the form (see below).
- post_target_url - send the POST request to this URL.
- params - query parameters for the POST request, formatted like this :
{param1 : 'value1', param2 : 'value2', ...}
And here’s the source code :
<script type='text/javascript' language='JavaScript'> function crossDomainPost(writer_url, post_target_url, params){ var url_params = ''; for (var key in params){ url_params =url_params + '&' + key + '='+encodeURIComponent(params[key]); } var url = writer_url + '?post_target_url=' + encodeURIComponent(post_target_url) + url_params; var iframe = document.createElement('iframe'); iframe.setAttribute('src', url); iframe.setAttribute('width', 1); iframe.setAttribute('height', 1); iframe.setAttribute('style', 'border: none;'); var p = document.getElementsByTagName('html'); p[0].appendChild(iframe); } </script>
The second component is the script that will generate and submit the form. There are several ways to create a form, but in this case I decided to stick with a mix of HTML & PHP. You can do it purely in JS, but the script would be a bit more complex. Either way, the form is still submitted by JavaScript, so the POST request will be done by the browser, not your server.
This script needs to be placed in a separate file (say, “form_writer.php”) because it will be loaded in a frame. Here’s the source :
<form method='post' action='<?php echo $_GET['post_target_url']; ?>' id='postform'> <?php unset($_GET['post_target_url']); foreach($_GET as $key => $value) { echo "<input type='hidden' name='$key' value='".htmlentities($value, ENT_QUOTES)."'>"; } ?> </form> <script language='JavaScript'> document.getElementById('postform').submit(); </script>
Using The Script
Lets see a real life example, shall we? Here’s how you can use the above scripts to send a trackback in JavaScript :
crossDomainPost( 'http://mydomain.com/form_writer.php', 'http://random-site.com/blog/offtopic/an-example-post/trackback/', { title : 'My Cool Post', excerpt : '...like, totally and such...', url : 'http://mydomain.com/stuff/my-cool-post/', blog_name : 'My Cool Blog' } );
Eeevil








You can even try to receive result
Script in the iframe can chage parent’s hash in URL so.. before post, run a “listener” (like function called with interval) to watch #hash value, then post, PHP after post should generete a response javascript that will put result in the hash, “listener” function can catch it
there is a limitation in url length, but you can split result in smaller chunks
I thought about doing something like that, but the assumption here is that you’re interacting with an external, third-party target that isn’t built to take advantage of this possibility. This whole thing would be much easier if you had control of the script that receives the POST.