# Bad value “” for attribute “src” on element “X”: Must be non-empty.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-for-attribute-src-on-element-x-must-be-non-empty
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `src` attribute has to contain a URL whenever it's present, so `src=""` or a value made only of spaces is invalid on every element that takes it.

The validator reports this on `<img>`, `<iframe>`, `<script>`, `<video>`, `<audio>`, `<source>`, `<track>`, `<embed>` and `<input type="image">`. A bare `src` with no value counts as empty too, and gets a second warning of its own.

The empty value usually comes from a template or CMS that prints `src` even when the URL field is blank, or from markup that waits for a script to fill in the URL. Write the attribute only when there is a URL, and leave out the whole element when it's useless without one.

Whether you can just drop `src` depends on the element:

- `<img>` needs `src` or `srcset`, so removing the attribute only swaps this error for another one. Output the image only when you have its URL. For lazy loading, keep the real URL in `src` and add `loading="lazy"`. If a script copies the real URL from `data-src` later, put a small placeholder image in `src` until then. Keep a meaningful `alt` either way, since that text is what people get when the image doesn't load.
- `<iframe>` works without `src`. For a frame that a script fills in later, leave `src` out or write `about:blank`, then set the real URL from the script. Browsers already load `about:blank` for an empty `src`, so writing it out changes nothing on screen. To embed a piece of HTML rather than a URL, use `srcdoc`.
- `<script>` with inline code shouldn't have `src` at all. Browsers ignore the code between the tags whenever `src` is present, and an empty `src` just fails to load, so that code never runs. The validator reports the inline code too.
- `<video>` and `<audio>` take either a `src` attribute or `<source>` children, not both. A `src` attribute, even an empty one, makes the browser ignore the `<source>` elements, so nothing plays even when each of them points to a real file. That's also why the validator reports those `<source>` children as not allowed. Remove `src` and keep the `<source>` list, or put the real URL in `src` and drop the `<source>` elements.
- `<source>` and `<track>` require `src`, so give the real URL or remove the element. Browsers skip a `<source>` with an empty `src` and try the next one, and if it was the only one, the media doesn't play. Inside `<picture>`, `<source>` takes `srcset` instead, and a `src` there triggers a different error.
- `<embed>` and `<input type="image">` need the URL of the file they show. An image button that has no image is better written as a plain `<button>`.

## Invalid example

```html
<img src="" alt="Our team at the spring meetup">

<iframe src="" title="Store locations map"></iframe>

<script src="">
  document.documentElement.classList.add("js");
</script>

<video controls width="640" height="360" src="">
  <source src="/media/product-tour.mp4" type="video/mp4">
  <source src="/media/product-tour.webm" type="video/webm">
</video>

<audio controls>
  <source src="/media/episode-12.ogg" type="audio/ogg">
  <source src=" " type="audio/mpeg">
</audio>
```

## Valid example

Give each element its real URL, and drop `src` where the files or the code are already inside the element:

```html
<img src="/images/team.jpg" alt="Our team at the spring meetup" loading="lazy">

<iframe src="/maps/stores.html" title="Store locations map"></iframe>

<script>
  document.documentElement.classList.add("js");
</script>

<video controls width="640" height="360">
  <source src="/media/product-tour.mp4" type="video/mp4">
  <source src="/media/product-tour.webm" type="video/webm">
</video>

<audio controls>
  <source src="/media/episode-12.ogg" type="audio/ogg">
  <source src="/media/episode-12.mp3" type="audio/mpeg">
</audio>
```

When a script loads the image or the frame later, start with a placeholder image and a blank frame:

```html
<img src="/images/placeholder.svg" data-src="/images/team.jpg" alt="Our team at the spring meetup">

<iframe src="about:blank" title="Store locations map" id="store-map"></iframe>
<script>
  document.getElementById("store-map").src = "/maps/stores.html";
</script>
```
