<commit_before>project_path: /web/fundamentals/_project.yaml
book_path: /web/fundamentals/_book.yaml
description: Most browsers can get access to the user's camera.

{# wf_updated_on: 2021-01-26 #}
{# wf_published_on: 2016-08-23 #}
{# wf_blink_components: Blink>ImageCapture #}

# Capturing an Image from the User {: .page-title }

{% include "web/_shared/contributors/paulkinlan.html" %}
{% include "web/_shared/contributors/mscales.html" %}

Many browsers now have the ability to access video and audio input from the
user. However, depending on the browser it might be a full dynamic and inline
experience, or it could be delegated to another app on the user's device. On top
of that, not every device even has a camera. So how can you create an experience
that uses a user generated image that works well everywhere?

## Start simple and progressively

If you want to progressively enhance your experience, you need to start with something that works
everywhere. The easiest thing to do is simply ask the user for a pre-recorded file.

### Ask for a URL
This is the best supported but least satisfying option. Get the user to give you a URL, and then
use that. For just displaying the image this works everywhere. Create an `img` element, set the
`src` and you're done.

Though, if you want to manipulate the image in any way, things are a bit more complicated.
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) prevents you from
accessing the actual pixels unless the server sets the appropriate headers and you
[mark the image as crossorigin](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image)
; the only practical way around that is to run a proxy server.

### File input
You can also use a simple file input element, including an `accept` filter that indicates you only
want image files.

    <input type="file" accept="image/*">

This method works on all platforms. On desktop it will prompt the user to
upload an image file from the file system. In Chrome and Safari on iOS and Android this method will
give the user a choice of which app to use to capture the image, including the option of taking a
photo directly with the camera or choosing an existing image file.

<img src="images/ios-chooser.png" />
<img src="images/android-chooser.png" />

The data can then be attached to a `<form>` or manipulated with JavaScript by
listening for an `onchange` event on the input element and then reading
the `files` property of the event `target`.

<pre class="prettyprint">
&lt;input type="file" accept="image/*" id="file-input">
&lt;script>
  const fileInput = document.getElementById('file-input');

  fileInput.addEventListener('change', (e) => doSomethingWithFiles(e.target.files));
&lt;/script>
</pre>

The `files` property is a `FileList` object, which I'll talk more about later.

You can also optionally add the `capture` attribute to the element, which indicates to the browser
that you prefer getting an image from the camera.

    <input type="file" accept="image/*" capture>
    <input type="file" accept="image/*" capture="user">
    <input type="file" accept="image/*" capture="environment">

Adding the `capture` attribute without a value let's the browser decide which camera to use, while<commit_msg>Fix render width of `2x` resolution screenshots (#9313)<commit_after>project_path: /web/fundamentals/_project.yaml
book_path: /web/fundamentals/_book.yaml
description: Most browsers can get access to the user's camera.

{# wf_updated_on: 2021-01-26 #}
{# wf_published_on: 2016-08-23 #}
{# wf_blink_components: Blink>ImageCapture #}

# Capturing an Image from the User {: .page-title }

{% include "web/_shared/contributors/paulkinlan.html" %}
{% include "web/_shared/contributors/mscales.html" %}

Many browsers now have the ability to access video and audio input from the
user. However, depending on the browser it might be a full dynamic and inline
experience, or it could be delegated to another app on the user's device. On top
of that, not every device even has a camera. So how can you create an experience
that uses a user generated image that works well everywhere?

## Start simple and progressively

If you want to progressively enhance your experience, you need to start with something that works
everywhere. The easiest thing to do is simply ask the user for a pre-recorded file.

### Ask for a URL
This is the best supported but least satisfying option. Get the user to give you a URL, and then
use that. For just displaying the image this works everywhere. Create an `img` element, set the
`src` and you're done.

Though, if you want to manipulate the image in any way, things are a bit more complicated.
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) prevents you from
accessing the actual pixels unless the server sets the appropriate headers and you
[mark the image as crossorigin](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image)
; the only practical way around that is to run a proxy server.

### File input
You can also use a simple file input element, including an `accept` filter that indicates you only
want image files.

    <input type="file" accept="image/*">

This method works on all platforms. On desktop it will prompt the user to
upload an image file from the file system. In Chrome and Safari on iOS and Android this method will
give the user a choice of which app to use to capture the image, including the option of taking a
photo directly with the camera or choosing an existing image file.

<img src="images/ios-chooser.png" width="250"/>
<img src="images/android-chooser.png" width="250"/>

The data can then be attached to a `<form>` or manipulated with JavaScript by
listening for an `onchange` event on the input element and then reading
the `files` property of the event `target`.

<pre class="prettyprint">
&lt;input type="file" accept="image/*" id="file-input">
&lt;script>
  const fileInput = document.getElementById('file-input');

  fileInput.addEventListener('change', (e) => doSomethingWithFiles(e.target.files));
&lt;/script>
</pre>

The `files` property is a `FileList` object, which I'll talk more about later.

You can also optionally add the `capture` attribute to the element, which indicates to the browser
that you prefer getting an image from the camera.

    <input type="file" accept="image/*" capture>
    <input type="file" accept="image/*" capture="user">
    <input type="file" accept="image/*" capture="environment">

Adding the `capture` attribute without a value let's the browser decide which camera to use, while
{'fraction_non_alphanumeric': 0.08618600424113905, 'fraction_numerical': 0.006513177824901545, 'mean_word_length': 4.672680412371134, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 31, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6887065', 'n_tokens_mistral': 1869, 'n_tokens_neox': 1765, 'n_words': 880}