---
title: "Add Responsive YouTube Videos to Astro.JS MDX"
description: "Embed responsive YouTube videos in Astro MDX using astro-embed. Faster loading, better performance scores, and privacy-friendly."
date: 2026-06-29
categories: ["cms"]
tags: ["astro","tutorials"]
---

import { Picture } from "astro:assets";
import imag1 from "../../assets/images/2210/video-speed-score.jpeg";

Standard YouTube iframes kill your page performance. They load 1-2 MB of JavaScript before the user even clicks play. Your Lighthouse score drops, and your visitors wait for scripts they may never use.

[astro-embed](https://www.npmjs.com/package/astro-embed) fixes this. It uses [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed) under the hood — a custom element that shows a thumbnail and only loads the full YouTube player on click. The result is approximately 224x faster than a standard embed.

This guide covers two ways to add YouTube videos to your Astro MDX files: manual imports and automatic URL conversion.

## Option 1: Manual import (recommended)

### Install astro-embed

```bash
npm i astro-embed
```

If you only need YouTube and want a smaller install, you can use the standalone package instead:

```bash
npm i @astro-community/astro-embed-youtube
```

### Import in your MDX file

Add the import statement in the frontmatter section of your `.mdx` file:

```mdx
---
title: "My Blog Post"
description: "A post with a video"
---

import { YouTube } from "astro-embed";

Your content here.

<YouTube id="https://youtu.be/NkShQ1wwiCg" />
```

If you installed the standalone package, import from there instead:

```mdx
import { YouTube } from "@astro-community/astro-embed-youtube";
```

### YouTube component props

The `<YouTube>` component accepts these props:

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | string | required | Video ID or full YouTube URL |
| `poster` | string | auto | Custom poster image URL |
| `posterQuality` | `'low'` \| `'default'` \| `'high'` \| `'max'` | `'default'` | Thumbnail resolution (120px to 1280px) |
| `params` | string | — | YouTube player parameters (e.g., `start=30&end=60`) |
| `playlabel` | string | `'Play'` | Accessible label for the play button |
| `title` | string | — | Overlay title text |

Examples:

```mdx
<!-- Basic embed -->
<YouTube id="NkShQ1wwiCg" />

<!-- Full URL also works -->
<YouTube id="https://www.youtube.com/watch?v=NkShQ1wwiCg" />

<!-- Start at 30 seconds, end at 90 -->
<YouTube id="NkShQ1wwiCg" params="start=30&end=90" />

<!-- Custom poster image -->
<YouTube id="NkShQ1wwiCg" poster="https://example.com/custom-thumb.jpg" />

<!-- With overlay title -->
<YouTube id="NkShQ1wwiCg" title="Watch the full tutorial" />
```

## Option 2: Auto-embed URLs in MDX

If you don't want to manually add `<YouTube>` components, you can install the auto-embed integration. It automatically converts plain YouTube URLs in your MDX content into embed components.

### Install

```bash
npm i @astro-community/astro-embed-integration
```

### Configure

Add the integration to your `astro.config.mjs`:

```js
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import embeds from '@astro-community/astro-embed-integration';

export default defineConfig({
  integrations: [mdx(), embeds()],
});
```

### Usage

Just paste a YouTube URL on its own line in your MDX file. No import needed:

```mdx
---
title: "My Post"
---

Check out this video:

https://youtu.be/NkShQ1wwiCg

The integration converts it to a `<YouTube>` component automatically.
```

This also works for Vimeo, Twitter/X posts, and Mastodon posts.

## Supported services

astro-embed supports more than YouTube. You can embed from:

- **YouTube** — `<YouTube>`
- **Vimeo** — `<Vimeo>`
- **Twitter/X** — `<Tweet>`
- **Mastodon** — `<MastodonPost>`
- **GitHub Gist**
- **Baseline status**
- **Open Graph** — `<LinkPreview>`

Import them all at once:

```mdx
import { YouTube, Vimeo, Tweet, MastodonPost, LinkPreview } from "astro-embed";
```

## Why this is faster than standard embeds

A normal YouTube `<iframe>` loads about 1.3-2.6 MB of JavaScript on page load — even if the visitor never plays the video. This tanks your Core Web Vitals.

The astro-embed approach:

1. Shows a lightweight thumbnail (poster image)
2. Loads zero YouTube JavaScript initially
3. Loads the full iframe only when the user clicks play
4. Uses `youtube-nocookie.com` for better privacy

The result: your page loads fast, your Lighthouse score stays high, and visitors only download YouTube's scripts if they actually want to watch.

<Picture
  src={imag1}
  alt="YouTube Speed score with astro-embed"
/>

## In Astro component files

You can also use astro-embed in `.astro` files, not just MDX:

```astro
---
import { YouTube } from "astro-embed";
---

<section>
  <h2>Featured Video</h2>
  <YouTube id="NkShQ1wwiCg" title="Featured tutorial" />
</section>
```

## Troubleshooting

**Component not rendering?** Make sure you have the `@astrojs/mdx` integration installed. Run `npx astro add mdx` if you haven't set it up yet.

**Import not found?** Check that you installed `astro-embed` (or the standalone package) and that the import path matches your install.

**Auto-embed not working?** Verify that `@astro-community/astro-embed-integration` is listed in your `integrations` array in `astro.config.mjs`, and that it comes after `mdx()`.

<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" />