The short answer

M3U is more widely accepted and easier to write by hand. XSPF is defined down to the element name, so an XML parser can tell you precisely what is broken instead of a player silently skipping a line. If a player offers both, M3U is the safer default for a simple list; XSPF is the better choice when the playlist travels between applications and must carry defined playlist-level fields.

What each one is

XSPF stands for XML Shareable Playlist Format, and it is pronounced "spiff". It was produced by the Playlist Ad-Hoc Group and sponsored by the Xiph.Org Foundation, with version 1 published in January 2005. The specification states plainly why it exists: almost every player accepts M3U, but also invents an XML playlist format of its own, and XSPF is meant to be the shared one.

M3U has no equivalent document. It grew by adoption, and the extended version added #EXTINF without anyone publishing a standard for it. That is not a defect for a list of file paths, but it means a wrong M3U file fails quietly, while a wrong XSPF file fails with an error that names the problem.

Structural difference

M3U XSPF
Foundation Plain text, one address per line XML document
Specification None published XSPF Version 1, January 2005
Media type None for the playlist itself application/xspf+xml
Root element Not applicable playlist, with version="1"
Namespace Not applicable http://xspf.org/ns/0/
Entry container The next line after #EXTINF trackList, then track
Address field The line itself location, expressed as a URI
Title and duration In #EXTINF Their own elements, alongside creator and album
Escaping None XML rules, so & must be escaped

One detail in that table is worth reading twice: the namespace is ns/0 while the version is 1. That is deliberate. Version 1 playlists are backwards compatible with version 0 parsers, so the namespace was left alone.

The same two tracks in both formats

As M3U:

#EXTM3U
#EXTINF:180,Opening song
Music/Opening.mp3
#EXTINF:240,Second song
Music/Second.mp3

As XSPF:

<?xml version="1.0" encoding="UTF-8"?>
<playlist version="1" xmlns="http://xspf.org/ns/0/">
  <title>Two songs</title>
  <trackList>
    <track>
      <location>file:///music/opening.mp3</location>
      <title>Opening song</title>
      <duration>180000</duration>
    </track>
    <track>
      <location>file:///music/second.mp3</location>
      <title>Second song</title>
      <duration>240000</duration>
    </track>
  </trackList>
</playlist>

Two differences stand out. XSPF durations are in milliseconds, so a three-minute track is 180000, not 180. And locations are URIs, which means a local file needs the file:/// prefix rather than a plain path. Passing the same address through a browser is a quick way to test whether a location is written correctly.

What XSPF is for, and what it is not

The specification is unusually blunt about this, and it corrects a common assumption. XSPF is not a catalogue of media metadata. The authors state that the function of a playlist is to identify objects and communicate their order, not to carry details about the composer or the song, and that a playlist format should not try to compete with the databases that already do that. Rich metadata is meant to arrive through the link and meta elements rather than through the core format.

So the structure XSPF adds is not a richer tag set. It is a defined shape: a playlist element that may carry a title, creator, annotation, date and licence, and exactly one trackList, whose track elements each list one or more candidate location URIs. The spec even calls those locations fuzzy names, because a track can be identified by a URI, a hash or a set of descriptive fields, and the player is trusted to resolve them.

That is also why every playlist element in the format is described as optional except the track list itself. Editable fields are conveniences; the requirement is that the document is well-formed and points at something renderable.

What a player must do with a broken track

One rule in the specification is worth knowing when debugging. If a track cannot be rendered, a player must skip it and must not stop the sequence. So an XSPF file whose fourth track is broken should still play the other three, and a player that stops entirely is not following the spec.

The duration field carries a similar warning. It is in milliseconds, but the spec calls it a hint and says a player must not use it to decide how long to render a track, because generators produce slightly different values. Treat it as a label, not as a control.

Symptom and cause

What you see Likely cause
Parser error naming a line Unescaped & or a tag closed in the wrong order
File parses but the player ignores every track location holds a plain path instead of a URI
Player rejects the document outright xmlns missing from the playlist element
Track list is empty Entries placed outside trackList, or misspelled with a lower-case l
Durations look absurdly long Seconds written where milliseconds are expected
Title has odd characters Entities not escaped, or the file saved in a non-UTF-8 encoding

Where the syntax bites

  • An unescaped ampersand. A stream address containing & is valid in M3U and breaks XSPF unless it is written as &amp;. This is the most common failure when converting.
  • trackList with a capital L. XML element names are case-sensitive, and tracklist is not the same element.
  • A missing namespace. A playlist element without xmlns is well-formed XML but not a usable XSPF document.
  • Plain paths instead of URIs. Music/Opening.mp3 is a valid M3U line and an invalid XSPF location.
  • Quiet failure the other way. An M3U file with a stray blank line or a missing header may open, with an entry silently missing, and give no clue why.

Which should you use

For a queue of local files that you will open in a desktop player, M3U is shorter and universally readable. Choose XSPF when the playlist must carry a title, a creator and per-track metadata, or when it is produced by an application that already writes XML and you want the output to be checkable against a published document. If you are generating playlists programmatically, XSPF is the friendlier target: an XML library handles the escaping, and a schema tells you when the output is wrong.

Writing one by hand

Start with the XML declaration, then a playlist element carrying version="1" and xmlns set to the XSPF namespace. Add an optional title and creator inside it, then one trackList. Every track goes inside that list as a track element, and every track needs at least one location holding a URI.

Keep the element order roughly as the specification lists it. XSPF defines a sequence for the children of each element, and while a lenient parser may accept any order, a strict one is entitled to reject a document that ignores it. Close every tag, and escape any ampersand in a URL.

If you are generating the file from code, let an XML library build the tree and serialise it. Hand-concatenating strings is how unescaped ampersands and stray angle brackets get into a playlist, and those are the failures that are hardest to see when you read the result in a browser, because the browser repairs them for display.

Converting between them

From M3U to XSPF: add the XML declaration and the playlist element with its namespace, wrap entries in trackList and track, move each address into location as a URI, move the title out of the #EXTINF line, and multiply the duration by 1,000. From XSPF to M3U: write #EXTM3U, then for each track write an #EXTINF line with the duration divided by 1,000 and the title, followed by the location.

Convert in a text editor or a script, and keep the original. Character entities are the part most likely to be damaged, because they exist in only one of the two formats.

Checking the result

The M3U file inspector reads .m3u and .m3u8 files in your browser and lists every line, so you can confirm an M3U file produced by a conversion. It does not open XSPF files. For the other comparisons, read M3U vs M3U8 and M3U vs PLS.

Where this information comes from

The XSPF details, including the namespace, the version, the trackList spelling, URI locations and the milliseconds convention, come from the XSPF Version 1 specification and its quickstart page. Statements about M3U describe common player behaviour, since the format has no published specification.