# Bad value for attribute “href” on element “a”: Illegal character in query: “[” is not allowed.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-for-attribute-href-on-element-a-illegal-character-in-query-square-bracket-is-not-allowed
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The W3C HTML Validator checks that URLs in `href` attributes conform to the URL standard (defined by WHATWG). While square brackets are permitted in the host component of a URL (to support IPv6 addresses like `[::1]`), they are **not** valid unescaped characters in the query string — the part of the URL that comes after the `?`. When the validator encounters a literal `[` or `]` in the query portion, it flags it as an illegal character.

This issue commonly arises when working with APIs or server-side frameworks that use square brackets in query parameters to represent arrays or nested data structures. For example, PHP-style query strings like `?filter[name]=foo` or `?ids[]=1&ids[]=2` contain brackets that must be encoded for valid HTML.

## Why this matters

- **Standards compliance:** The WHATWG URL Standard explicitly lists square brackets among the characters that must be percent-encoded in query strings. Invalid URLs cause W3C validation failures.
- **Browser behavior:** While most modern browsers are forgiving and will often handle unescaped brackets correctly, relying on this lenient parsing is fragile. Some HTTP clients, proxies, or intermediary servers may reject or mangle URLs with illegal characters.
- **Interoperability:** Encoded URLs are safer when copied, shared, or processed by tools like link checkers, web scrapers, or email clients that may perform strict URL parsing.

## How to fix it

Replace every literal square bracket in the query string with its percent-encoded form:

| Character | Percent-encoded |
|-----------|-----------------|
| `[`       | `%5B`           |
| `]`       | `%5D`           |

If you're generating URLs dynamically in a server-side language or JavaScript, use the appropriate encoding function (e.g., `encodeURIComponent()` in JavaScript, `urlencode()` in PHP, or `urllib.parse.quote()` in Python) to handle this automatically.

## Examples

### Incorrect: literal brackets in the query string

```html
<a href="https://example.com/search?filter[status]=active">Active items</a>
```

This triggers the validation error because `[` and `]` appear unescaped in the query.

### Correct: percent-encoded brackets

```html
<a href="https://example.com/search?filter%5Bstatus%5D=active">Active items</a>
```

Replacing `[` with `%5B` and `]` with `%5D` resolves the error. The server receiving this request will decode the values back to `filter[status]=active`.

### Incorrect: array-style parameters with brackets

```html
<a href="/api/items?ids[]=1&ids[]=2&ids[]=3">Load items</a>
```

### Correct: array-style parameters encoded

```html
<a href="/api/items?ids%5B%5D=1&amp;ids%5B%5D=2&amp;ids%5B%5D=3">Load items</a>
```

Note that in addition to encoding the brackets, the `&` characters in HTML attributes should be written as `&amp;` for fully valid markup.

### Incorrect: brackets in a simple value

```html
<a href="search.html?q=[value]">Search</a>
```

### Correct: encoded brackets in a simple value

```html
<a href="search.html?q=%5Bvalue%5D">Search</a>
```

### Note on brackets in the host (valid use)

Square brackets are valid in the **host** portion of a URL for IPv6 addresses. The following does **not** trigger the error:

```html
<a href="http://[::1]:8080/page">IPv6 localhost</a>
```

The validator only flags brackets that appear in the query string or other parts of the URL where they are not permitted.
