Error 403: when connecting to the Advanced Trade websocket using example code

I’m using the JS example from the website to try to subscribe to a websocket feed,

and I’m getting the following error Unexpected server response: 403

According to the debugger, this happens before any actual messages are sent to the websocket server.

Presumably immediately after connecting to wss://advanced-trade-ws.coinbase.com

My API key works without an issue using the Advanced Trade REST endpoints, and I’ve enabled all permissions for the API key.

Welcome to the Coinbase Cloud Developer forum, @ClauZ! To further help you with your concern, we suggest you to open a support ticket with our team with the following details:

  • Please specify which Websocket channel you are trying to subscribe to.
  • Please provide a code snippet to demonstrate the problem you are encountering including generating a Signature and Timestamp. Kindly ensure to exclude your API credentials for security reasons.

Upon creating a support ticket, kindly include the link of this forum so that the team will be aware that it’s you. Additionally, please use the email address associated with your Coinbase account.

Thank you and have a nice day!

well I basically copy pasted the code from the website, so it’s trying to subscribe to the “user” channel, but I’ve also tried the “status” channel and I have the same error.

The code is the one from the website, the only difference is that I pull the API key and API secret from environment variables.


// JS Example for subscribing to a channel
/* eslint-disable */
const WebSocket = require('ws');
const CryptoJS = require('crypto-js');
const fs = require('fs');

// Derived from your Coinbase Retail API Key
//  SIGNING_KEY: the signing key provided as a part of your API key. Also called the "SECRET KEY"
//  API_KEY: the api key provided as a part of your API key. also called the "PUBLIC KEY"
const SIGNING_KEY = process.env.API_SECRET;
const API_KEY = process.env.API_KEY;

if (!SIGNING_KEY.length || !API_KEY.length) {
  throw new Error('missing mandatory environment variable(s)');
}

const CHANNEL_NAMES = {
  level2: 'level2',
  user: 'user',
  tickers: 'ticker',
  ticker_batch: 'ticker_batch',
  status: 'status',
  market_trades: 'market_trades',
};

// The base URL of the API
const WS_API_URL = 'wss://advanced-trade-ws.coinbase.com';

// Function to generate a signature using CryptoJS
function sign(str, secret) {
  const hash = CryptoJS.HmacSHA256(str, secret);
  return hash.toString();
}

function timestampAndSign(message, channel, products = []) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const strToSign = `${timestamp}${channel}${products.join(',')}`;
  const sig = sign(strToSign, SIGNING_KEY);
  return { ...message, signature: sig, timestamp: timestamp };
}

const ws = new WebSocket(WS_API_URL);

function subscribeToProducts(products, channelName, ws) {
  const message = {
    type: 'subscribe',
    channel: channelName,
    api_key: API_KEY,
    product_ids: products,
  };
  const subscribeMsg = timestampAndSign(message, channelName, products);
  ws.send(JSON.stringify(subscribeMsg));
}

function unsubscribeToProducts(products, channelName, ws) {
  const message = {
    type: 'unsubscribe',
    channel: channelName,
    api_key: API_KEY,
    product_ids: products,
  };
  const subscribeMsg = timestampAndSign(message, channelName, products);
  ws.send(JSON.stringify(subscribeMsg));
}

function onMessage(data) {
  const parsedData = JSON.parse(data);
  fs.appendFile('Output1.txt', data, (err) => {
    // In case of a error throw err.
    if (err) throw err;
  });
}

const connections = [];
let sentUnsub = false;
for (let i = 0; i < 1; i++) {
  const date1 = new Date(new Date().toUTCString());
  const ws = new WebSocket(WS_API_URL);

  ws.on('message', function (data) {
    const date2 = new Date(new Date().toUTCString());
    const diffTime = Math.abs(date2 - date1);
    if (diffTime > 5000 && !sentUnsub) {
      unsubscribeToProducts(['BTC-USD'], CHANNEL_NAMES.user, ws);
      sentUnsub = true;
    }

    const parsedData = JSON.parse(data);
    fs.appendFile('Output1.txt', data, (err) => {
      // In case of a error throw err.
      if (err) throw err;
    });

  });

  ws.on('open', function () {
    const products = ['BTC-USD'];
    subscribeToProducts(products, CHANNEL_NAMES.status, ws);
  });

  connections.push(ws);
}

I’ll open that support ticket as well…

Hi @ClauZ! We appreciate all the information that you have provided. Once you successfully log a support ticket, we will be glad to quickly assist you with your concerns. Please ensure that the details you provided are also included in the support ticket.

Thank you and have a nice day!

1 Like

Hello @ClauZ !

As you requested to drop a message through the forum to verify if we are actually the personnel representing Coinbase, here is the message to confirm that we are from the Coinbase team trying to help you with your issue regarding the Websocket feed subscription. Please share your confidential information which we have requested through email.

Thank you for your patience and understanding.

1 Like

will do, thanks for confirming, I’m currently not home, but as soon as I get home I’ll send you an e-mail with the requested info. :+1:

Any headway on this issue ?

Hi @ClauZ! Please be informed that the team is still hard at work in finding a resolution with regard to your concern. Please know that your case is being dealt with priority and we will provide an update once we have found an answer. We really appreciate your patience and understanding.

1 Like

I too had similar issues. I presented a lot of troubleshooting evidence from my end with no real progress. The Coinbase team says ‘they’re working on it’.

Hi @tripster202! We sincerely apologize for the delay in our response. As of the moment, the internal team is still looking into this. Rest assured that this is already communicated and taken care of and will get back to you once we have any updates. We appreciate your patience and understanding. Thank you and have a great day!