Markdown extension to allow media embedding using the oEmbed standard.
Find a file
2026-03-03 15:37:31 +01:00
mdx_oembed Refactor and Update python-markdown-oembed-extension 2026-03-03 14:26:52 +01:00
.gitignore use flit packaging tool, write simple test 2023-11-06 18:58:32 +01:00
LICENSE added license and manifest template, bumped alpha version 2012-11-13 16:55:47 -06:00
pyproject.toml Refactor and Update python-markdown-oembed-extension 2026-03-03 14:26:52 +01:00
README.md Update README for version 0.5.0: require Python >= 3.12, enhance installation instructions, and add changelog details 2026-03-03 15:37:31 +01:00
tests.py Refactor and Update python-markdown-oembed-extension 2026-03-03 14:26:52 +01:00
uv.lock Refactor and Update python-markdown-oembed-extension 2026-03-03 14:26:52 +01:00

Python Markdown oEmbed

Markdown extension to allow media embedding using the oEmbed standard.

Requirements

  • Python >= 3.12
  • Markdown >= 3.2

Installation

pip install python-markdown-oembed-extension

Or with uv:

uv add python-markdown-oembed-extension

Usage

import markdown
md = markdown.Markdown(extensions=['oembed'])
md.convert('![video](http://www.youtube.com/watch?v=zqnh_YJBvOI)')

Output is wrapped in a <figure class="oembed"> element by default:

<figure class="oembed"><iframe width="459" height="344" ...></iframe></figure>

Configuration

Option Default Description
allowed_endpoints YouTube, Flickr, Vimeo, Slideshare List of oembed.OEmbedEndpoint objects
wrapper_class "oembed" CSS class(es) for the <figure> wrapper. Set to "" to disable wrapping

Example with custom configuration:

from mdx_oembed.endpoints import YOUTUBE, VIMEO

md = markdown.Markdown(
    extensions=['oembed'],
    extension_configs={
        'oembed': {
            'allowed_endpoints': [YOUTUBE, VIMEO],
            'wrapper_class': 'embed-responsive',
        }
    }
)

Security

oEmbed HTML responses are sanitized using nh3 to prevent XSS from compromised oEmbed providers. Only safe tags (iframe, video, audio, img, etc.) and attributes are allowed.

License

A Public Domain work. Do as you wish.

Changelog

0.5.0

  • Breaking: requires Python >= 3.12
  • Replaced custom html.escape() for proper attribute escaping in photo <img> tags
  • HTTP status validation: non-2xx oEmbed API responses now raise OEmbedError
  • addEndpoint() is deprecated in favour of add_endpoint() (emits DeprecationWarning)
  • Added from __future__ import annotations to all modules
  • Added py.typed marker (PEP 561) for downstream type-checking support
  • Version is now sourced dynamically from mdx_oembed/version.py via hatch
  • Added ruff and pyright configuration in pyproject.toml
  • Tests converted to pure pytest (dropped unittest.TestCase)
  • New tests for HTTP status handling, deprecation warnings, and HTML escaping
  • Removed legacy src/ package tree

0.4.0

  • Breaking: requires Python >= 3.9 and Markdown >= 3.2
  • Migrated from deprecated Pattern to InlineProcessor (Markdown 3.2+ compatible)
  • Added HTML sanitization of oEmbed responses (XSS protection via nh3)
  • Added support for oEmbed photo type responses
  • Improved image URL detection (case-insensitive, handles query strings)
  • All oEmbed API endpoints now use HTTPS
  • Slideshare URL patterns now accept both HTTP and HTTPS
  • Configurable <figure> wrapper class (previously hardcoded Bootstrap classes)
  • Migrated to pyproject.toml with hatchling build backend
  • Tests modernized: uses pytest + unittest.mock, all HTTP calls mocked
  • Centralized version management in mdx_oembed/version.py

0.2.1

  • add Slideshare endpoint (thanks to anantshri)

0.2.0

  • backwards incompatible changes
    • allows arbitrary endpoints (commit)
    • works with modern Markdown (>=2.6)
    • dropped support for python 2.6
  • added support python 3.x