Ajax request: Refused to set unsafe header
Asked Answered
D

3

34

I am trying to play an audio using Google Text-To-Speech. Therefore I need to post a request to their endpoint with the Referer and the User-Agent properly set. This call should return an MP3 that I can play.

However, I get Refused to set unsafe header errors. This is my code. How can I do this?

          $.ajax({
            url: 'http://translate.google.com/translate_tts?ie=UTF-8&q=Hello&tl=en&client=t',
            beforeSend: function(xhr) {
                 xhr.setRequestHeader("Referer", "http://translate.google.com/");
                 xhr.setRequestHeader("User-Agent", "stagefright/1.2 (Linux;Android 5.0)");
            }, success: function(data){
                el.mp3 = new Audio(data);
                el.mp3.play();
            }
          });
Dredger answered 15/10, 2015 at 8:41 Comment(4)
Possible duplicate of Add Header in AJAX Request with jQueryEusebiaeusebio
Doesn't matter what header you set, the Google translate endpoint doesn't support CORSPromptbook
From cURL it works...Dredger
@Arturo — For cURL you are making the request yourself, you aren't asking your visitor's browser to quietly do it in the background on your behalf. There are lots of extra security restrictions when you try to make other people's browsers do things.Zygospore
Z
53

You can't. It is impossible.

The specification requires that the browser abort the setRequestHeader method if you try to set the Referer header (it used to be that User-Agent was also forbidden but that has changed)..

If you need to set Referer manually then you'll need to make the request from your server and not your visitor's browser.

(That said, if you need to be deceptive about the user agent or referer then you are probably trying to use the service in a fashion that the owner of it does not want, so you should respect that and stop trying).

Note that while jQuery wraps XHR, the same rules apply to fetch.

Zygospore answered 15/10, 2015 at 9:0 Comment(1)
Not necessarily. There are a number of privacy-related situations where sending an empty referrer and origin are entirely reasonable. For example, suppose you have a government age verification site. A request from your server or from the client with a populated referrer and origin means the government knows exactly who visited specific sites. There's no legitimate reason for any government to know that information, so this should be sent anonymously, with no referrer. Of course, one could argue that this is "trying to use the service in a fashion that the owner of it does not want". 😁Citriculture
E
3

Empty Origin and Referer headers with GET XMLHttpRequest from <iframe>

Well actually, it is possible; at least for ordinary web pages. The trick consists in injecting an XMLHttpRequest function into an empty <iframe>. The origin of an empty <iframe> happens to be about://blank, which results in empty Origin and Referer HTTP headers.

HTML:

<iframe id="iframe"></iframe>

JavaScript:

const iframe    = document.getElementById('iframe');
const iframeWin = iframe.contentWindow || iframe;
const iframeDoc = iframe.contentDocument || iframeWin.document;

let script = iframeDoc.createElement('SCRIPT');

script.append(`function sendWithoutOrigin(url) {
    var request = new XMLHttpRequest();

    request.open('GET', url);

    request.onreadystatechange = function() {
        if(request.readyState === XMLHttpRequest.DONE) {
            if(request.status === 200) {
                console.log('GET succeeded.');
            }
            else {
                console.warn('GET failed.');
            }
        }
    }
    request.send();
}`);

iframeDoc.documentElement.appendChild(script);

JavaScript evocation:

var url  = 'https://api.serivce.net/';
    url += '?api_key=' + api_write_key;
    url += '&field1=' + value;

iframeWin.sendWithoutOrigin(url);

Having the possibility of sending empty Origin and Referer HTTP headers is important to safeguard privacy when using third-party API services. There are instances where the originating domain name may reveal sensitive personal information; like being suggestive of a certain medical condition for example. Think in terms of https://hypochondriasis-support.org :-D

The code was tested by inspecting the requests in a .har file, saved from the Network tab in the F12 Developer View in Vivaldi.

No attempt in setting the User-Agent header was made. Please, comment if this also works.

Emersed answered 24/3, 2021 at 13:56 Comment(0)
F
1

There are some header, which browser doesn't allow programmer to set its value in any of the javascript framework (like jQuery, Angular, etc.) or XMLHttpRequest ; while making AJAX request. These are called the forbidden headers: Forbidden Header

Forta answered 11/1, 2023 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.