Twilio

Twilio Error 12300

Twilio Error 12300 means your webhook returned a Content-Type Twilio can't process. Return text/xml for TwiML and a supported audio MIME type for Play.

Updated Jul 1, 2026

The short answer

Twilio Error 12300 "Invalid Content-Type" means Twilio fetched your webhook (or media) URL but the response's Content-Type header is one it cannot process for that context. Fix it by returning text/xml or application/xml for TwiML, returning a supported audio MIME type (e.g. audio/mpeg, audio/wav) for the <Play> verb, and always sending a Content-Type header so the request isn't treated as 502.

Twilio raises Error 12300 — Invalid Content-Type when it makes an HTTP request to one of your URLs (a voice/messaging webhook, an action/StatusCallback URL, or a media URL referenced by <Play>) and the response comes back with a Content-Type header that is invalid for how Twilio intends to use it. Twilio decides how to interpret your response based on this header, so a mismatch — for example serving TwiML as application/json or pointing <Play> at an XML document — stops it cold.

What causes Twilio Error 12300?

There are two distinct mismatches behind almost every 12300:

  1. A TwiML endpoint returns a non-TwiML Content-Type. When Twilio requests TwiML, it expects the response to be served as text/xml or application/xml (it also accepts text/html). A common trap is a framework or serializer that emits application/json by default — e.g. ASP.NET Web API without XML formatters configured, or an Express handler that calls res.json() or passes a JS object to res.send() instead of sending a raw XML string with an explicit Content-Type: text/xml header. The body may be valid XML, but the header tells Twilio it's JSON, so it refuses to parse it.
  2. A <Play> verb points at non-audio content. <Play> requires the fetched file to be served with a supported audio MIME type. Pointing it at an XML/TwiML document, an HTML error page, or a file your storage host serves as application/octet-stream/text/plain triggers 12300.

A related failure: returning no Content-Type header at all. Twilio surfaces those requests in the Debugger as a 502 Bad Gateway rather than 12300, but the underlying cause is the same — set the header explicitly.

Per Twilio's <Play> documentation, the supported audio MIME types are: audio/mpeg, audio/wav, audio/wave, audio/x-wav, audio/aiff, audio/x-aifc, audio/x-aiff, audio/x-gsm, audio/gsm, and audio/ulaw.

How do I fix Twilio Error 12300?

  1. Open the Twilio Console Debugger and find the 12300 event. It names the exact URL Twilio called and the Content-Type it received — that tells you whether the offending endpoint is a TwiML webhook or a <Play> media URL.
  2. For a TwiML response, force the XML Content-Type. Make your handler set Content-Type: text/xml (or application/xml) explicitly rather than relying on a JSON-by-default serializer. Most server SDKs do this for you when you return a VoiceResponse/MessagingResponse object instead of a hand-built string.
HTTP/1.1 200 OK
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Thanks for calling.</Say>
</Response>
  1. For <Play>, verify the media URL serves a supported audio type. Open the URL directly and check the response header (curl -I <url>). If your object store (S3, IBM Cloud Object Storage, etc.) serves the file as application/octet-stream or text/plain, set the object's Content-Type metadata to the correct audio type, e.g. audio/mpeg for an MP3.
  2. If you only need to acknowledge an incoming request without responding, the right response depends on the endpoint. For StatusCallback and other informational webhooks that don't expect TwiML, a 200 OK with no body is documented as sufficient. For incoming message/voice webhooks that expect a TwiML response, Twilio's own guidance is to return 200 OK with Content-Type: text/xml and an empty <Response/> body.
  3. Re-trigger the call/message and confirm the Debugger event clears.

If you send through Courier and route SMS/voice via a Twilio integration, the TwiML/media responses still originate from your own endpoints — apply the same Content-Type fixes there; Courier does not rewrite the headers your server returns.

FAQ

Common questions

Twilio decides how to parse your response from the Content-Type header, not the body. If your server sends valid TwiML but labels it application/json (a common framework default), Twilio rejects it with 12300. Set the header to text/xml or application/xml.

One API, every provider

Stop debugging raw provider errors

Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.

Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.