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.
The five usual causes
| Cause | Example | Fix |
|---|---|---|
| No scheme | example.com/page | Add https:// |
| Misspelled scheme | htp://example.com | Use http or https |
| Illegal character | https://example.com/my file.pdf | Encode it: my%20file.pdf |
| Broken % sequence | ?discount=100% | Write a literal % as %25 |
| Bad port or IPv6 host | http://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.
| Where | Input | Error |
|---|---|---|
Java 21 new URL(s) | example.com/page | java.net.MalformedURLException: no protocol: example.com/page |
Java 21 new URL(s) | htp://example.com | java.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/page | java.lang.IllegalArgumentException: URI is not absolute |
Node 22 new URL(s) | example.com/page | TypeError: Invalid URL (code ERR_INVALID_URL) |
Chrome new URL(s) | example.com/page | TypeError: Failed to construct 'URL': Invalid URL |
JavaScript decodeURIComponent | 100% | URIError: URI malformed |
| curl 8.5 | http://exa mple.com/ | curl: (3) URL rejected: Malformed input to a URL function |
| curl 8.5 | http://example.com:99999/ | curl: (3) URL rejected: Port number was not a decimal number between 0 and 65535 |
| curl 8.5 | http://example.com/?a={b | curl: (3) unmatched brace in URL position 23: |
| curl 8.5 | htp://example.com/ | curl: (1) Protocol "htp" not supported or disabled in libcurl |
| Python requests 2.34 | example.com/page | MissingSchema: Invalid URL 'example.com/page': No scheme supplied. Perhaps you meant https://example.com/page? |
Python 3.13 urllib.request | example.com/page | ValueError: unknown url type: 'example.com/page' |
Python 3.13 urlparse(...).port | http://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()giveshttps://example.com/my%20file.pdf?q=a%20b.new URL(String)is deprecated since Java 20; useURI.create(s).toURL(). - JavaScript — check before parsing with
URL.canParse(s), or wrapnew URL(s)intry/catch. Build queries withURLSearchParams, and encode single values withencodeURIComponent. - 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 withurllib.parse.quote(value, safe="")or pass a dict toparams=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
- RFC 3986 — the URI syntax a well-formed URL must follow (§3) and percent-encoding (§2.1). rfc-editor.org/rfc/rfc3986
- WHATWG URL Standard — the parsing rules browsers and Node use, including when
new URL()throws. url.spec.whatwg.org - Java java.net.URL and java.net.URI; curl error codes; MDN URL.canParse().
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.
More guides
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.