The command
curl -H "Accept: application/xml" https://httpbin.org/xml
Opens the request console with this request filled in. It is sent from api-tester.com's server rather than from your machine, so it shows what the endpoint returns, not how your own network or curl build behaves.
What the flags do
| Flag | What it does |
|---|---|
-H "Accept: application/xml" | Ask for XML. Feeds may want application/rss+xml or application/atom+xml. |
-s | No progress meter, so the output can go straight into a parser. |
--compressed | Accept gzip and decompress it. Sitemaps and feeds are often served compressed. |
-o file.xml | Save the document instead of printing it. |
Formatting and querying the response
Servers send XML on a single line or with whatever indentation their serialiser produced. xmllint --format re-indents it. The same tool evaluates XPath, which is the dependable way to take one value out of a document: wrap the path in string() for text, or count() for a number of elements. The trailing dash tells xmllint to read from the pipe.
curl -s -H "Accept: application/xml" https://httpbin.org/xml | xmllint --format -
curl -s https://httpbin.org/xml | xmllint --xpath "string(//slide[1]/title)" -
curl -s https://httpbin.org/xml | xmllint --xpath "count(//slide)" -
Sitemaps, feeds and namespaces
The XML most people fetch is not from an API at all: it is a sitemap, an RSS or Atom feed, or a configuration document. Many of these declare a default namespace on the root element, and an XPath such as //loc then matches nothing, because the element's full name includes that namespace. Matching on local-name() sidesteps it without having to register a prefix.
curl -s --compressed https://example.com/sitemap.xml \
| xmllint --xpath "//*[local-name()='loc']/text()" -
curl -s -H "Accept: application/rss+xml" https://example.com/feed \
| xmllint --xpath "//item/title/text()" -
Checking what actually came back
Accept is a preference, and a server is free to ignore it. Before parsing, look at the status code and the response's own Content-Type; both are available as write-out variables while the body goes to a file. Saving to a file also helps with character sets: curl does not convert encodings, so a document declared as ISO-8859-1 looks garbled in a UTF-8 terminal yet is read correctly by a parser that honours the XML declaration.
curl -s -o feed.xml -w "%{http_code} %{content_type}\n" \
-H "Accept: application/xml" https://httpbin.org/xml
Common mistakes
- An XPath that returns nothing usually means a namespace. Elements in a default namespace are not matched by their bare names.
- An HTML error page is not XML. A 404 or a login redirect fed to a parser produces a parse error far from the real cause.
- Avoid grep and sed for anything beyond a quick look. Attribute order, line breaks and entity encoding all vary between equivalent documents.
Related curl examples
Curl POST XML Example
XML over HTTP works like JSON over HTTP with different media types, plus one extra header if the service speaks SOAP.
Curl GET JSON Example
Fetching JSON is a GET with one header that says what you want back.
Curl GET Request Example
GET is what curl does when you give it nothing but a URL.
Curl Send Header Example
-H adds a header line to the request.
All Curl Examples
49 worked examples, grouped by what you are trying to do.
More under Request bodies
References
- curl man page: -H — Adding a request header such as Accept.
- MDN: XPath — The query language used to pull values out of an XML document.
These links leave api-tester.com, which is independent of the projects they point to.
FAQ
How do I get XML with curl?
Send a GET request with an Accept header for XML: curl -H "Accept: application/xml" URL. The XML response body is printed to the terminal.
How do I pretty-print XML from curl?
Pipe the output to xmllint: curl -s URL | xmllint --format - indents the document so it is readable.
How do I extract a value from an XML response on the command line?
Pipe curl into xmllint with an XPath expression, for example curl -s URL | xmllint --xpath "string(//title)" - to print the text of the first title element.