Forum Discussion
Tighter security settings in browsers can impact dynamically loaded JavaScript libraries.
- 7 months ago
CORS Errors with pdf-lib and Storyline — Why You Should Switch from unpkg.com to jsDelivr to dynamically load code
I promised a fuller explanation - and here it is. Over the years I have posted several examples here (and seen my code appearing in other posts) where I suggested using the JavaScript library pdf-lib to create downloadable notes or certificates.
If your Storyline project has used any of my code (or other code derived from it) and it suddenly starts throwing CORS errors when generating PDFs, here’s what’s likely happening — and how to fix it.
The Problem: CORS errors from unpkg.com
In the original code, I used dynamic import() calls to load external JavaScript libraries like this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
This worked fine, but now browsers are enforcing stricter CORS (Cross-Origin Resource Sharing) rules, especially for JavaScript module imports.
That unpkg.com link doesn't return the proper Access-Control-Allow-Origin header, which causes this error:
Access to script at 'https://unpkg.com/...' from origin '...' has been blocked by CORS policy...
This will prevent your Storyline course from loading the library at runtime, causing PDF generation to fail.
✅ The Solution: Switch to jsDelivr
To resolve this, you simply need to load the library from a CDN that does send the correct CORS headers — like jsDelivr.
Replace this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
With this:
PDFLib = await import("https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.esm.min.js");
(Don’t forget to declare let PDFLib; at the top of your script to make it available globally - I hadn't done that in my original examples and, it worked but was risky!)
If you’re also using tiny-save-as to download the generated PDF, you’ll need to do the same in this section of code:
await import("https://cdn.jsdelivr.net/npm/tiny-save-as@1.0.1/dist/tiny-save-as.esm.min.js")
.then(({ default: saveAs }) => { saveAs(new Blob([pdfBytes]), filename); });
Why This Matters
- unpkg.com doesn’t always send CORS headers for ESM imports
- jsDelivr is fully CORS-compliant and supports modern module usage
- This fix makes your Storyline + PDF solution reliable across all modern browsers and LMS platforms
CORS Errors with pdf-lib and Storyline — Why You Should Switch from unpkg.com to jsDelivr to dynamically load code
I promised a fuller explanation - and here it is. Over the years I have posted several examples here (and seen my code appearing in other posts) where I suggested using the JavaScript library pdf-lib to create downloadable notes or certificates.
If your Storyline project has used any of my code (or other code derived from it) and it suddenly starts throwing CORS errors when generating PDFs, here’s what’s likely happening — and how to fix it.
The Problem: CORS errors from unpkg.com
In the original code, I used dynamic import() calls to load external JavaScript libraries like this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
This worked fine, but now browsers are enforcing stricter CORS (Cross-Origin Resource Sharing) rules, especially for JavaScript module imports.
That unpkg.com link doesn't return the proper Access-Control-Allow-Origin header, which causes this error:
Access to script at 'https://unpkg.com/...' from origin '...' has been blocked by CORS policy...
This will prevent your Storyline course from loading the library at runtime, causing PDF generation to fail.
✅ The Solution: Switch to jsDelivr
To resolve this, you simply need to load the library from a CDN that does send the correct CORS headers — like jsDelivr.
Replace this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
With this:
PDFLib = await import("https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.esm.min.js");
(Don’t forget to declare let PDFLib; at the top of your script to make it available globally - I hadn't done that in my original examples and, it worked but was risky!)
If you’re also using tiny-save-as to download the generated PDF, you’ll need to do the same in this section of code:
await import("https://cdn.jsdelivr.net/npm/tiny-save-as@1.0.1/dist/tiny-save-as.esm.min.js")
.then(({ default: saveAs }) => { saveAs(new Blob([pdfBytes]), filename); });
Why This Matters
- unpkg.com doesn’t always send CORS headers for ESM imports
- jsDelivr is fully CORS-compliant and supports modern module usage
- This fix makes your Storyline + PDF solution reliable across all modern browsers and LMS platforms
- ToddVillari7 months agoCommunity Member
Thank you. This is exactly what happened in Chrome some time back.
- JohannesBurke7 months agoCommunity Member
hi there,
thanks a lot for sharing this.(Don’t forget to declare let PDFLib
Dumb question but how do I declare the PDFlib? Can you input the code here? Sorry but I'm a noob regarding javascript.
Regards,
John- JMorrison7 months agoCommunity Member
I would love to know what the code is for this line as well JohnCooper-be3c
Thanks so much!!!
- ToddVillari7 months agoCommunity Member
Stick it right here.