---
title: "How To Embed Youtube Videos to Gatsby"
description: "Embed YouTube videos in Gatsby markdown and MDX using plugins. Step-by-step setup for Contentful and other headless CMS systems."
date: 2026-06-26
categories: ["web-development"]
tags: ["gatsby"]
---

import Button from "../../components/widgets/Button.astro";

**Note:** Gatsby has been in maintenance mode since 2023. The latest release (v5.16.1, February 2026) added React 19 and Node.js 24 support, but active feature development has stopped. If you're starting a new project, consider [Next.js](https://nextjs.org/) or [Astro](https://astro.build/) instead. The instructions below still work for existing Gatsby sites.

Gatsby doesn't handle iframes out of the box. You can't just paste a YouTube embed code into markdown and expect it to work — React sanitizes raw HTML. You need a plugin to convert video URLs into proper iframes during the build.

This guide covers two approaches: using a remark plugin for markdown content, and handling videos in MDX with a custom component.

## Option 1: gatsby-remark-embed-video (recommended)

[gatsby-remark-embed-video](https://www.gatsbyjs.com/plugins/gatsby-remark-embed-video/) is the most maintained option in the Gatsby ecosystem. It supports YouTube, Vimeo, VideoPress, and Twitch. Last published 4 years ago (v3.2.1), but it still works with Gatsby 5.

It works with both `gatsby-transformer-remark` (markdown) and `gatsby-plugin-mdx`.

### Install

```bash
npm i gatsby-remark-embed-video gatsby-transformer-remark
```

If you want responsive iframes (recommended), also install:

```bash
npm i gatsby-remark-responsive-iframe
```

### Configure for markdown (gatsby-transformer-remark)

Add this to your `gatsby-config.js`:

```javascript
{
  resolve: "gatsby-transformer-remark",
  options: {
    plugins: [
      {
        resolve: "gatsby-remark-embed-video",
        options: {
          width: 800,
          ratio: 1.77,           // 16/9 aspect ratio
          height: 400,           // overrides ratio if set
          related: false,        // hide related videos at end
          noIframeBorder: true,
          loadingStrategy: "lazy",
          containerClass: "embedVideo-container",
          urlOverrides: [
            {
              id: "youtube",
              embedURL: (videoId) =>
                `https://www.youtube-nocookie.com/embed/${videoId}`,
            },
          ],
        },
      },
      "gatsby-remark-responsive-iframe",  // must come after embed-video
    ],
  },
},
```

The `youtube-nocookie.com` URL override uses YouTube's privacy-enhanced mode — no cookies until the user clicks play. Good for GDPR compliance.

### Configure for MDX (gatsby-plugin-mdx)

If you're using MDX instead of plain markdown:

```javascript
{
  resolve: "gatsby-plugin-mdx",
  options: {
    gatsbyRemarkPlugins: [
      {
        resolve: "gatsby-remark-embed-video",
        options: {
          width: 800,
          ratio: 1.77,
          related: false,
          noIframeBorder: true,
          loadingStrategy: "lazy",
        },
      },
      "gatsby-remark-responsive-iframe",
    ],
  },
},
```

### Usage in content

Add these tags on their own line in your markdown or MDX files:

```
`video: https://www.youtube.com/embed/2Xc9gXyf2G4`

`youtube: https://www.youtube.com/watch?v=2Xc9gXyf2G4`
`youtube: 2Xc9gXyf2G4`

`vimeo: https://vimeo.com/5299404`
`vimeo: 5299404`

`videoPress: https://videopress.com/v/kUJmAcSf`
`videoPress: kUJmAcSf`

`twitch: https://player.twitch.tv/?channel=dakotaz`
`twitch: https://player.twitch.tv/?autoplay=false&video=v273436948`
`twitch: 273436948`
`twitchLive: dakotaz`
```

You can also add accessibility titles:

```
`youtube: [My Video Title](https://www.youtube.com/watch?v=2Xc9gXyf2G4)`
```

### Using with Contentful CMS

This approach works with Contentful or any headless CMS that outputs markdown. The key requirement: **your content field must be markdown, not rich text.**

In Contentful, create a text field with "Markdown" type. Then add the video tag on its own line in the editor:

```
`youtube: https://youtu.be/2Wmats7Q6ck`
```

When Gatsby builds, `gatsby-transformer-remark` processes the markdown and the embed-video plugin converts the tag into an iframe.

### Important: plugin order matters

If you use `gatsby-remark-responsive-iframe`, `gatsby-remark-images`, or `gatsby-remark-prismjs`, the embed-video plugin must come first:

```javascript
plugins: [
  "gatsby-remark-embed-video",
  "gatsby-remark-responsive-iframe",
  "gatsby-remark-prismjs",
  "gatsby-remark-images",
]
```

Wrong order will break video embedding.

## Option 2: Custom React component (MDX only)

If you're using MDX and want more control, skip the plugin entirely and create a YouTube component:

```jsx
// src/components/YouTube.js
const YouTube = ({ id, title = "YouTube video" }) => (
  <div style={{ position: "relative", paddingBottom: "56.25%", height: 0, overflow: "hidden" }}>
    <iframe
      src={`https://www.youtube-nocookie.com/embed/${id}`}
      title={title}
      style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }}
      allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
      allowFullScreen
      loading="lazy"
    />
  </div>
);

export default YouTube;
```

Then import and use it in your MDX files:

```mdx
import YouTube from "../components/YouTube";

# My Post

Some content here.

<YouTube id="2Xc9gXyf2G4" title="Demo video" />
```

This gives you full control over the iframe attributes, styling, and lazy loading. No plugin dependency.

## Which approach to choose

**Use the plugin if:**
- Your content comes from a headless CMS (Contentful, Sanity, etc.)
- Non-technical editors need to add videos by pasting URLs
- You have existing markdown content with video tags

**Use a custom component if:**
- You write content directly in MDX files
- You want full control over iframe attributes
- You want to avoid plugins that haven't been updated in years

## Troubleshooting

**Videos not showing up?** Check that your content field is markdown type, not rich text. Rich text in Contentful uses a different rendering pipeline that skips remark plugins.

**Build errors after install?** Clear the Gatsby cache:
```bash
gatsby clean && gatsby develop
```

**Plugin conflicts?** Make sure embed-video is listed before any other remark plugins in your config.

<Button link="https://go.bitdoze.com/do" text="DigitalOcean $100 Free" />
<Button link="https://go.bitdoze.com/vultr" text="Vultr $100 Free" />
<Button link="https://go.bitdoze.com/hetzner" text="Hetzner €20 Free" />
<Button link="https://go.bitdoze.com/hostinger-vps" text="Hostinger VPS" />