tiagosiebler / binance

Node.js & JavaScript SDK for Binance REST APIs & WebSockets, with TypeScript & browser support, integration tests, beautification & more.
MIT License
750 stars 266 forks source link

Binance APIs in the frontend & CORS #194

Closed sergiocard closed 2 years ago

sergiocard commented 2 years ago

Hi, i'm using this library on browser. I know its intented for backend use but i'm prototyping and would to use it in browser. I'm using const client= new MainClient({ api_key: '**', api_secret: '', beautifyResponses: true })

client.testNewOrder(buyOrderRequest)

but i get following CORS errors. image

Should the POST request contains an Access-Control-Request-Headers header for "x-mbx-apikey" header?

Looking into binance dev area it seems it's possible to make browser side calls only for public apis. Can you confim? I'm thinking i could use a local proxy to forward local browser calls to binance server instead? for example with cors-anywhere npm module

tiagosiebler commented 2 years ago

When directly making a request from a browser to a backend (in this case binance is the backend), CORS should be addressed by the backend. The backend essentially defines what is acceptable - in this case binance's APIs are not configured to accept this header (among many other CORS headers binance's APIs sadly are not configured for).

Bybit suffers the same limitation. Using your own CORS proxy is certainly an option (but not a public one), but safer would be to have these kind of API calls be triggered by your own backend. Some explanations here from a similar discussion in my bybit connector (which works very similarly): https://github.com/tiagosiebler/bybit-api/issues/79#issuecomment-780756907

I would also recommend nudging binance about this - perhaps increased demand will nudge them enough to prioritise configuring their APIs for CORS. Hope this helps.

sergiocard commented 2 years ago

ok thanks. I used "cors-anywhere" npm package temporarily and it let me forward request to api.binance.com Now i have another problem: url is not well encoded on newOrderTest as shown below:

Cattura

so the api returns 400 bad request because url query params are maformed

tiagosiebler commented 2 years ago

Are you on the latest version? This was fixed in #180. v2.0.21 or above.

tiagosiebler commented 2 years ago

Also, once you get up and running, it'd be useful for others if you could write some kind of tutorial or high level summary on how to get this working in the browser (incl cors-anywhere implementation). Even a lazy example repo would be helpful.

niebieskiRydz commented 1 year ago

Hi, did you manage to make it work correctly? I think my signature is ok but the fact the call is from frontend is the issue. I tried cors-anywhere and http-proxy-middleware. I can't manage to have the proper response :(

tiagosiebler commented 1 year ago

Hi, did you manage to make it work correctly? I think my signature is ok but the fact the call is from frontend is the issue. I tried cors-anywhere and http-proxy-middleware. I can't manage to have the proper response :(

My recommendation is to make signed requests through a backend (this way your API keys are also not exposed to the browser). This would avoid the CORS limitation from binance as well as reduce risk to those API keys, although it would mean maintaining some backend APIs that your frontend can use. You would also need to consider rate limits, since your backend would be making API calls (likely from the same IP), although you would see this with cors-anywhere too.

sergiocard commented 1 year ago

you need following 3 points:

1)launch "npm install cors-anywhere" 2) launch "node proxy" where proxy.js provide a proxy server listening on http://127.0.0.1:8080

// Listen on a specific host via the HOST environment variable
var host = process.env.HOST || '127.0.0.1';
// Listen on a specific port via the PORT environment variable
var port = process.env.PORT || 8080;

var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
    originWhitelist: [], // Allow all origins
    requireHeader: ['origin', 'x-requested-with'],
    removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
    console.log('Running CORS Anywhere on ' + host + ':' + port);
});

3) initialize the binance client with something like:

import { MainClient } from 'binance'

const proxy = 'http://127.0.0.1:8080/'
const baseUrl = 'https://api.binance.com'
const realClient = new MainClient({
    api_key: 'your_api_key',
    api_secret: 'your_api_secret',
    beautifyResponses: false,
    baseUrl: proxy + baseUrl,
    recvWindow: 40000
}) 

This way requests will reach the local proxy as first, then the proxy will handle the cors headers

niebieskiRydz commented 1 year ago

tiagosiebler and sergiocard thank you for your help! Before I set cors-anywhere wrong. It works now and I have a proper response from Binance! 🥳