-1

I'm trying to connect with an external API and have to add a cookie to my POST call, but it seems the length is too long for puppeteer (13.5.0)?

EDIT

After some experimenting, it seems that the issue is not the length, but the use of the char ";". Is there a way to fix that?

As mentioned in the comments I've tried encodeURIComponent(), although the call is getting processed (instead of giving an error) the server is not letting it pass and throws an error back, when I use it in postman, the not encoded cookie works, the encoded cookie doesn't work.

According to this most modern backends have decoding, the one we're using apparently doesn't (it's a pretty old one). Semicolons however should not be illegal to use.

ref. RFC 2965 page 12, paragraph 3

Note: For backward compatibility, the separator in the Cookie header is semi-colon (;) everywhere.

END EDIT

When I do it in my javascript

await page.setCookie({name: 'Cookie', value: cookie, domain: 'https://www.example.com'});

When I set the cookie value to a shorter string, without a semicolon, the call seems to work. But with the necessary cookie I get an error message.

The error:

error: new Errors_js_1.ProtocolError(),
       ^

ProtocolError: Protocol error (Network.setCookies): Invalid cookie fields
    at C:\Users\james\OneDrive\Bureaublad\connector\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:230:24
    at new Promise (<anonymous>)
    at CDPSession.send (C:\Users\james\OneDrive\Bureaublad\connector\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:226:16)
    at Page.setCookie (C:\Users\james\OneDrive\Bureaublad\connector\node_modules\puppeteer\lib\cjs\puppeteer\common\Page.js:772:32)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async loginRequest (C:\Users\james\OneDrive\Bureaublad\connector\connector.js:46:5) {
  originalMessage: 'Invalid cookie fields'
}

the cookie I need to use (433 chars long):

Shortloin=alcatrasalami80er~SOCbiltongvenisonk/zPA==;chicken=leberkasdrumstickboudinbuffalofrankfurtershortribshamburger;Cowfatback=capicola;brisket=frankfurtersausageshanklelandjaegerdrumstickbacontonguechuckpigchislicbresaola;Cupimp=icanhabresaolaleberkas;Pancetta=picanhagroundroundbresaola;Tailcapicolaballtipmeatloaftenderloinchislicshankcornedbeefcowburgdoggen;Brisketdrumsticktenderloinshankporchetta;alcatratur=duckenTailswinesalamipicanha 

I've tried the same method in postman, where I just added the cookie in the headers page with one key using semicolons and the call worked fine.

Minimal reproducible example:

const puppeteer = require('puppeteer');
const loginPage = 'https://stackoverflow.com/';

async function login() {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.setCookie({name: 'Cookie', value: 'cookie=test;test=cookie' , domain: 'stackoverflow.com'}); 
    await page.goto(loginPage);
}

login();
James D
  • 1,975
  • 2
  • 17
  • 26

1 Answers1

0

It looks like you are conflating the value of an individual cookie with the cookie string that gets included in HTTP request headers.

// whoops, passing an etnire cookie string instead of the cookie value
await page.setCookie({name: 'Cookie', value: 'cookie=test;test=cookie' , domain: 'stackoverflow.com'}); 

You can either pass a cookie string (e.g. cookie=test;test=cookie) within your HTTP request (which I think is what you are doing with postman), or set a cookie in the browser window that will get included in subsequent HTTP requests.

page.setCookie allows you to set a cookie in the browser and, conveniently takes an array of cookies (see https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagesetcookiecookies).

So if you want to pass multiple cookies you can do so like this:

const cookies = [
  { name: 'cookie', value: 'test', domain: 'stackoverflow.com' },
  { name: 'test', value: 'cookie', domain: 'stackoverflow.com' },
];

await page.setCookie(...cookies);
Daniel Grant
  • 156
  • 6