CORS error for fetching stock price

I am using a script to fetch stock prices from https://financialmodelingprep.com/api/v3/quote-short/?{stock}?apikey=*

I run it and the CORS error pops up saying it is unable to fetch the data.
Then sometimes Ill click it and it’ll fetch but return the price undefined…

Any workaround to having this work a bit better? Here is my code if anyone is curious

output.markdown ("# Updating stock prices");

let table = base.getTable (“Stocks”),
records = await table.selectRecordsAsync ();

await Promise.all (

records.records.map (async record => {

    let stock = record.getCellValue ("Ticker");

    if (! stock) {

        output.text ("Can't update the price of stock with no name");

        return;
    }

    output.text (`Updating price of ${stock}...`);

    // make request
    var requestResult = await fetch (
        `https://financialmodelingprep.com/api/v3/quote-short/${stock}?apikey=*`
    ).then (r => r.json ());

    // print fetched data
    output.markdown (`${stock}'s price right now is: **$${requestResult.price}**`)

    // update record in table
    return await table.updateRecordAsync (record, {
        "CSP": requestResult.price,
        "CSP Date": new Date ()
    });
})

);

output.markdown ("# Done!");

Have you seen this?

I’m still learning external APIs, but I recently found that blocks will throw CORS errors if there is an error in my script that’s unrelated to the server’s CORS support.

This is typically the case; it’s really the browser encountering an error that it cannot discern the nature of. And we can’t really blame the Script Block; this is coming from the client whose security settings are attempting to honor the restrictions imposed by cross-domain interchanges.

I’ve removed a majority of the code and its still freezing up :confused: Also tried with three different browsers, What the heck am I doing wrong here?

output.markdown ("# Updating stock prices");

let table = base.getTable ("Stocks"),
    records = await table.selectRecordsAsync ();

await Promise.all (

    records.records.map (async record => {

        let stock = record.getCellValue ("Ticker");

        if (! stock) {

            output.text ("Can't update the price of stock with no name");

            return;
        }

        // make request
        var requestResult = await fetch (
            `https://financialmodelingprep.com/api/v3/stock/real-time-price/${stock}?apikey=*`
        ).then (r => r.json ());

        // update record in table
        return await table.updateRecordAsync (record, {
            "CSP": requestResult.price,
            "CSP Date": new Date ()
        });
    })
);

output.markdown ("# Done!");

Is a space allowed in this context? Shouldn’t it be maybe r.json()? And what does freezing up mean? Are there specific error messages you can share from the javascript console?

Good syntax suggestion, but made no difference on CORS. This is wildly annoying. I’ve now tried in safari, chrome, and brave. No dice. Sometimes it will fetch a few quotes, but then show the error anyways. I’m not trying to fetch this every hour. Maybe once a month. Maybe there is a better API handler I can GET instead of the current website? Any suggestions?

Screen Shot 2020-06-11 at 07.58.06

Indeed, and unfortunately, sidestepping CORS may not be in your user’s best interest.

Any site your browser visits can make cross-site requests to any domain it wants, with relatively few restrictions. Abuse of this functionality is known as Cross-Site Request Forgery (CSRF). CSRF has been around for 15 years, and for most of that time, CSRF tokens were the only solution. More recently, this new browser standard was developed to allow “safe” cross-origin requests: HTML5 Cross-Origin Resource Sharing (CORS). In reality, CORS has opened up a new attack surface for cross-site requests and made preventing them way more complex.

I noticed that your code provides no HEADERS such as Access-Control-Allow-Origin; have you experimented with them including no-cors?

Well, I think I’m lacking some skills in this hunt for the proper design pattern to help you make this work partly because I rarely build integrations that access the Airtable API directly (from client). Rather, almost every use case where Airtable data is required, I buffer that interaction with a NodeJS layer and in many cases I build these in everyday Google Apps Script (it is fundamentally serverless-side javascript not unlike NodeJS).

Through experience I’ve found that this approach is more resilient, it’s impervious to possible outages in Airtable (there aren’t many, but it helps to have apps that fail with grace and integrity), and it eliminates the CORS calamity altogether. It’s my chicken-sh*t way of dodging challenging roadblocks while sustaining profitability. :slight_smile:

Depending on the app/data size and performance requirements, I tend to cache-forward data into Firebase or ElasticSearch, but in some cases a simple Google Sheet does the job quite well.

If I could give you a huge reddit gold trophy I would. Thanks for your help! Really appreciate it :slight_smile: Ill work on a few different implementations and see if anything sticks

@Chris_Finck out of curiosity, did you get this working? I just tried it and it worked for me, so I wonder if financialmodelingprep.com changed their API to allow cross-origin (CORS) requests.

It’s spotty. Sometimes it works. Sometimes not. Can I see your code?

I was just testing:

const response = await fetch('https://financialmodelingprep.com/api/v3/quote-short/AAPL?apikey=<MY API KEY>');
const json = await response.json();
output.inspect(json);
1 Like