I have a Next.js app with the following structure:
.
├── next.config.js
└── src /
└── app/
├── page.tsx
└── getYoutubeTranscript/
└── getYoutubeTranscript.tsx
next.config.js
has the following policy defined:
// @ts-check
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" }, //http://localhost:3000
{ key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
]
}
]
}
}
module.exports = nextConfig
page.tsx
is a client component that uses the getYoutubeTranscript
server component to fetch a Youtube transcript. But when this code executes I get the client-side error:
Access to fetch at 'https://www.youtube.com/watch?v=<ID>' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Looks like I misconfigured CORS in next.config.js
— any tips here to further diagnose?
Update #1: I don’t see a Host listed in the Request Headers of my call from Developer Console? This answer implies when Host != Origin that causes the error
Update #2: Here are the Response Headers (two images):
2
Answers
The pattern of inserting a Server component into a Client component isn't supported by Next.js: https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#unsupported-pattern-importing-server-components-into-client-components
I think you have misunderstood CORS. You try to fetch some youtube URLs from localhost (with xhr I assume) which YOUTUBE doesn’t allow with its CORS. Changing your own API CORS will allow other sites to fetch from your API
I also have a couple of notes on the question/update:
/api/
path but I can’t see any in your screenshot of the structure.Now, guessing a bit here since I can’t be sure of what happens here, if you want to fetch a youtube video in your NextJS app, you need to fetch it FROM an API or a server component.
Anyways… You say that the
getYoutubeTranscript
is a server component and it fetches from youtube so I also think there is an error in the definition here somewhere since, if it was, you wouldn’t have any CORS issues. I guess a missing'use server'
somewhere…My 2 cents on an alternative: As a rule, I never change my
page.tsx
to client components so that I can always fetch the necessary data there.Final note: As far as I know, you are not allowed to fetch
youtube.com/watch
URLs only the embedded ones. Youtube videos will actually not play if not on their domains. But I may be mistaken here…