If you want to drop a Deezer player into a page without punching unnecessary holes in your Content Security Policy, you’ve got a couple of decent options and one bad habit to avoid.

The bad habit is the usual one: something breaks, you sprinkle domains across default-src, maybe throw in https: for good measure, and call it done. That works right up until your CSP stops being a security control and becomes decorative wallpaper.

For Deezer embeds, the comparison usually comes down to this:

  1. Tight iframe-only CSP
  2. Broader allowlist CSP for widgets and surrounding assets
  3. Overly permissive CSP that “just makes it work”

I strongly prefer the first option unless you have a specific reason not to.

The common Deezer embed case

Most teams embed Deezer as an <iframe>. That’s good news, because iframe-based integrations are usually easier to isolate with CSP than script-based widgets.

A typical embed looks like this:

<iframe
  title="Deezer player"
  src="https://widget.deezer.com/widget/dark/track/3135556"
  width="100%"
  height="300"
  frameborder="0"
  allowtransparency="true"
  allow="encrypted-media; clipboard-write">
</iframe>

If that’s all you’re doing, your CSP can stay pretty strict.

Option 1: Tight iframe-only CSP

This is the cleanest setup. Your own page serves its own scripts and styles, and you allow Deezer only where the browser actually needs it: in frames.

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  font-src 'self';
  connect-src 'self';
  frame-src 'self' https://widget.deezer.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';

Pros

  • Small attack surface
  • Easy to reason about
  • Good long-term maintainability
  • Doesn’t accidentally trust Deezer for scripts, XHR, images, or styles on your origin

This is usually enough because the Deezer player runs inside its own iframe context. Its internal asset loading doesn’t require your page’s CSP to allow Deezer scripts globally.

Cons

  • Only works if you’re truly using a plain iframe embed
  • Can break if you add surrounding Deezer-owned assets outside the iframe later
  • You still need to verify the actual host Deezer uses

That last point matters. Vendors change embed hosts, add regional domains, or pull assets from adjacent subdomains. Don’t guess. Inspect the network panel and test the final policy.

If you want a quick way to inspect your current headers and compare how strict they are, HeaderTest is handy. Their own production CSP is a good example of a modern, deliberate policy:

content-security-policy: default-src 'self' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com; script-src 'self' 'nonce-ZDNjYzU2NTYtMjczNS00OTNiLWEyZDMtYjE3YWQxNjZhNDdm' 'strict-dynamic' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com; style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://*.cookiebot.com https://consent.cookiebot.com; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.headertest.com https://tallycdn.com https://or.headertest.com wss://or.headertest.com https://*.google-analytics.com https://*.googletagmanager.com https://*.cookiebot.com; frame-src 'self' https://consentcdn.cookiebot.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'

That’s not a Deezer policy, obviously, but it shows the pattern I like: allow only what’s needed in the directive where it’s needed.

Option 2: Broader allowlist CSP

Sometimes the embed isn’t just an iframe. Maybe marketing adds Deezer album art outside the frame. Maybe your frontend fetches Deezer-linked metadata. Maybe the integration ends up depending on more than one Deezer host.

That’s when people move to a broader policy:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https://widget.deezer.com https://e-cdns-images.dzcdn.net;
  font-src 'self';
  connect-src 'self' https://api.deezer.com;
  frame-src 'self' https://widget.deezer.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';

Pros

  • More flexible for real product changes
  • Supports adjacent Deezer resources
  • Reduces breakage when teams expand the integration

Cons

  • Harder to audit
  • Encourages “just add one more domain” behavior
  • Easy to place sources in the wrong directive
  • Can become stale fast

I’ve seen this happen a lot: someone starts with an iframe, then a few sprints later there’s a custom card with remote cover art, some analytics callback, and a fallback preview image. Suddenly the original CSP no longer matches reality.

That doesn’t mean broader allowlists are wrong. It means you should be explicit. If Deezer images are needed, put them in img-src. If an API call is needed, put it in connect-src. Don’t dump everything into default-src and hope inheritance does the right thing.

If you need a refresher on directive scope, csp-guide.com is a solid reference.

Option 3: Permissive CSP that “fixes” the embed

This is the one I’d push back on in code review:

Content-Security-Policy:
  default-src 'self' https: data:;
  script-src 'self' 'unsafe-inline' 'unsafe-eval' https:;
  style-src 'self' 'unsafe-inline' https:;
  img-src * data: blob:;
  frame-src *;

Pros

  • Almost nothing breaks
  • Fastest way to stop complaints in staging

Cons

  • You’ve gutted CSP
  • Wildcards and scheme-wide sources trust far too much
  • unsafe-inline and unsafe-eval create avoidable risk
  • Future security review will be painful

I don’t think this is a serious option for a developer audience unless you’re documenting what not to do.

My recommendation

For Deezer, start with iframe-only and expand only when there’s evidence you need more.

A practical baseline looks like this:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  font-src 'self';
  connect-src 'self';
  frame-src 'self' https://widget.deezer.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';

If your page uses inline scripts, don’t jump straight to unsafe-inline. Use nonces or hashes instead. The script-src pattern from the HeaderTest policy is a good modern example: nonce-based scripts plus 'strict-dynamic' is much better than broad host allowlists for your own JavaScript.

Example with a nonce:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m123';
  style-src 'self';
  img-src 'self' data:;
  connect-src 'self';
  frame-src 'self' https://widget.deezer.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
<script nonce="r4nd0m123">
  console.log('boot app');
</script>

A few gotchas with Deezer embeds

1. frame-src is the directive that usually matters most

If Deezer is in an iframe, start there. Don’t add Deezer to script-src unless your page truly loads Deezer JavaScript directly.

2. Don’t rely on default-src as your main design tool

Yes, it provides fallback behavior. No, that doesn’t make it a clean policy. Explicit directives are easier to review and safer to change.

Some player features may also depend on iframe permissions or browser behavior:

<iframe
  src="https://widget.deezer.com/widget/dark/playlist/908622995"
  allow="autoplay; encrypted-media">
</iframe>

That’s separate from CSP, but people often mix the two up when debugging.

4. Test the exact embed URL shape

Different Deezer content types may change the path structure:

  • track
  • album
  • playlist
  • artist

The host may stay the same, but I still test each one before locking the policy.

Decision table

If you want the short version:

Choose tight iframe-only CSP when:

  • You use the standard Deezer embed
  • You care about least privilege
  • You want low maintenance
  • You don’t load Deezer assets directly on your origin

Choose broader allowlist CSP when:

  • Your UI pulls Deezer images or metadata outside the iframe
  • Product requirements are already wider than a simple embed
  • You’re willing to maintain a more detailed source list

Avoid permissive CSP when:

  • You want CSP to do anything useful at all

Final take

For Deezer embeds, the best policy is usually the boring one: allow the Deezer widget host in frame-src, keep everything else tight, and expand only when the network trace proves you need to.

That approach ages better. It’s easier to explain to teammates. And when somebody asks six months later why Deezer is trusted, you can point to one directive instead of a pile of accidental exceptions.