Malformed URL: what it means and how to fix it.

A URL is malformed when it breaks URL syntax — almost always a missing https://, a space or other illegal character, a broken % sequence, or an impossible port. Paste yours below to see which.

Why is this URL malformed?

The five usual causes

CauseExampleFix
No schemeexample.com/pageAdd https://
Misspelled schemehtp://example.comUse http or https
Illegal characterhttps://example.com/my file.pdfEncode it: my%20file.pdf
Broken % sequence?discount=100%Write a literal % as %25
Bad port or IPv6 hosthttp://example.com:99999/Port 0–65535; IPv6 in [ ]

The exact error messages

Each language words it differently. These were captured by running the code, with the versions shown.

WhereInputError
Java 21 new URL(s)example.com/pagejava.net.MalformedURLException: no protocol: example.com/page
Java 21 new URL(s)htp://example.comjava.net.MalformedURLException: unknown protocol: htp
Java 21 new URL(s)https://exa mple.com/java.net.MalformedURLException: Illegal character found in host: ' '
Java 21 URI.toURL()example.com/pagejava.lang.IllegalArgumentException: URI is not absolute
Node 22 new URL(s)example.com/pageTypeError: Invalid URL (code ERR_INVALID_URL)
Chrome new URL(s)example.com/pageTypeError: Failed to construct 'URL': Invalid URL
JavaScript decodeURIComponent100%URIError: URI malformed
curl 8.5http://exa mple.com/curl: (3) URL rejected: Malformed input to a URL function
curl 8.5http://example.com:99999/curl: (3) URL rejected: Port number was not a decimal number between 0 and 65535
curl 8.5http://example.com/?a={bcurl: (3) unmatched brace in URL position 23:
curl 8.5htp://example.com/curl: (1) Protocol "htp" not supported or disabled in libcurl
Python requests 2.34example.com/pageMissingSchema: Invalid URL 'example.com/page': No scheme supplied. Perhaps you meant https://example.com/page?
Python 3.13 urllib.requestexample.com/pageValueError: unknown url type: 'example.com/page'
Python 3.13 urlparse(...).porthttp://example.com:99999/ValueError: Port out of range 0-65535

Note that Python’s urlparse("example.com/page") doesn’t raise anything — it quietly returns the whole string as a path with an empty host, so the failure shows up later.

Fixing it in code

Build URLs from parts instead of gluing strings. Each language has a constructor that encodes for you:

  • Java — the multi-argument constructor quotes illegal characters: new URI("https", "example.com", "/my file.pdf", "q=a b", null).toURL() gives https://example.com/my%20file.pdf?q=a%20b. new URL(String) is deprecated since Java 20; use URI.create(s).toURL().
  • JavaScript — check before parsing with URL.canParse(s), or wrap new URL(s) in try/catch. Build queries with URLSearchParams, and encode single values with encodeURIComponent.
  • curl — quote the URL in the shell, encode spaces as %20, send parameters with --data-urlencode, and add -g (--globoff) when the URL contains [ ] or { } so curl doesn’t treat them as patterns.
  • Python — make sure the string starts with https://, and encode values with urllib.parse.quote(value, safe="") or pass a dict to params= in requests.

Malformed is not the same as broken

A malformed URL fails before any request is sent — the program can’t even read it. A well-formed URL can still fail: a 404 means the server has no such page, a DNS error means the host doesn’t exist, and a 400 or 431 means the server rejected what it received. If the checker above finds nothing, look at those instead — see debugging 404s caused by bad parameters and fixing HTTP 431.

Sources & standards

Common questions.

The string doesn’t follow URL syntax, so the program can’t parse it at all. The usual causes are a missing https://, a space or other illegal character, a broken % sequence, or an invalid port.

The string has no scheme. Add https:// (or http://) at the start. If the value comes from user input or configuration, check for leading spaces and quotes too.

CURLE_URL_MALFORMAT — curl couldn’t parse the URL. Typical causes are spaces (encode as %20), an invalid port, or [ ]/{ } being read as glob patterns (add -g).

The input contains a % that isn’t followed by two hex digits — often a literal percent sign such as “100%” — or bytes that aren’t valid UTF-8. Encode literal percent signs as %25.

Strictly, yes: spaces aren’t allowed in URLs. Browsers quietly encode them for you, but curl, Java and most HTTP libraries reject them, so encode spaces as %20.

More from the toolkit.

About this page. Written and maintained by Sri Murugan Systems, the developer of urlencodedecode.com. Error messages on this page were captured by running each runtime, not copied from memory; versions are listed where they appear.