#66080·pandas

BUG: to_html with render_links=True and escape=True does not escape the href attribute

Author: Str1ckl4ndCreated Jun 28, 2026Updated Sep 17, 2026
LabelsBugIO HTML
### Pandas version checks - [x] I have checked that this issue has not already been reported. - [x] I have confirmed this bug exists on the [latest version](https://pandas.pydata.org/docs/whatsnew/index.html) of pandas. - [x] I have confirmed this bug exists on the [main branch](https://pandas.pydata.org/docs/dev/getting_started/install.html#installing-the-development-version-of-pandas) of pandas. ### Reproducible Example ```python import pandas as pd value = 'http://example.com/search?q=a"b&lang=en' html = pd.DataFrame({"url": [value]}).to_html(render_links=True, escape=True) print(html) assert "http://example.com/search?q=a"b&lang=en" in html assert 'href="http://example.com/search?q=a"b&lang=en"' in html ``` ### Issue Description `DataFrame.to_html(render_links=True, escape=True)` escapes the visible cell text, but the generated `href` attribute uses the original cell value without the same HTML escaping. The relevant implementation is in `pandas/io/formats/html.py`: ```python rs = pprint_thing(s, escape_chars=esc).strip() if self.render_links and is_url(rs): rs_unescaped = pprint_thing(s, escape_chars={}).strip() start_tag += f'' ``` With the value from the example above, the visible cell text is escaped as expected, but the `href` attribute keeps the raw double quote and ampersand. The generated table therefore has different escaping behavior between the visible URL text and the generated link URL. Current generated output includes this shape: ```html http://example.com/search?q=a"b&lang=en ``` This is surprising because `escape=True` changes the visible text to `"` and `&`, while `render_links=True` keeps the raw characters in the generated `href`. ### Expected Behavior When `escape=True` and `render_links=True` are both enabled, the generated anchor should apply consistent HTML escaping to the URL value before placing it in `href`. For example, the generated output should represent the same URL value consistently in both the anchor's `href` attribute and the visible link text. ### Installed Versions Directly visible environment information: - pandas: 3.0.3 - Python container image: python:3.13-slim Reproduced with pandas `3.0.3`. The same `rs_unescaped` implementation is also present on the current `main` branch at `pandas/io/formats/html.py`.