Ai-Thinker ESP32-CAM in the Arduino IDE


Setting up the Ai-Thinker ESP32-CAM with the Arduino IDE Camera Web Server example.

The AI-Thinker ESP32-CAM module features an ESP32-S chip, an OV2640 camera and a microSD card slot. They have them on AliExpress here. There are other ESP32 based camera modules available that should work if the pins are set in the sketch.

If you prefer to work with your ESP32 in the Espressif IDF there’s another guide here: ESP32 Camera Module with Face Recognition

Adding or Updating the ESP32 Range in the Arduino IDE

If you’ve never used an ESP32 board in the Arduino IDE you need to follow the first part of this tutorial: ESP32 Built-in OLED Heltec WiFi Kit 32
If you already have the ESP32 boards available in your IDE then you just need to update to the latest version of the board libraries. To do this, open the Arduino IDE and in the menu: Tools > Board:xxxxx > Boards Manager:

Boards Manager

Search for ESP32:

Boards Manager ESP32

Update this to the latest version.


The ESP32-CAM doesn’t come with a USB connector so you need either a CP2102 or a FT232RL USB to TTL Serial Converter to connect it to your PC. When using WiFi the ESP32 can use more current than is supplied via USB through these devices resulting in the module crashing and rebooting. I found the top device worked fine (I bought it here) but the FT232RL wouldn’t work without a separate supply to the 5V pin.

USB to ESP32-CAM Wiring Diagram


Wire the module according to the diagram above. The green connection should be connected when flashing the module and disconnected when running.

Running the Camera Web Server Example

Plug in your module and change the board settings to these:

IDE Camera Settings

Open the Sketch by navigating  File > Examples > ESP32 > Camera > CameraWebServer:

Camera Web Server Sketch

Edit the Sketch defines to look like this (assuming you are using the Ai-Thinker module):

// Select camera model

Change the following two lines to match your WiFi connection details:

const char* ssid = "NSA";
const char* password = "orange";

Click Upload to build and flash the Sketch to your device.

If you get an error that the device fails to connect. Check that the IO0 pin (green in the diagram) is connected to GND and press the reset button under the module and try again.

When the device has completed flashing, unplug IO0 from GND.

Open the serial monitor via Tools > Serial Monitor.

Press the reset button on the ESP32-CAM and watch the start up sequence in the serial monitor:

Camera Web Server Startup

Look for the IP address that the ESP32 has been given on your network.

Type that IP address into your browser. You should be able to see a GUI on the left where you can control elements of the camera, set face detection and face recognition. Click Get Still to take a photo. Click Start Stream to see a video stream from the camera.


On-Board vs IPEX Antenna

A few people have commented that they have received the board with the antenna jumper set for an external antenna rather than the on-board antenna. You can see the two different settings below:

Antenna Jumper Settings on the ESP32-CAM

If you have a low frame rate or poor reception this might well be the problem. You can either move the jumper with a bit of very careful soldering or buy an IPEX WiFi antenna which will improve the signal.

ESP32-CAM Video Playlist

IF you prefer your tutorials in video format you can visit the Robot Zero One YouTube channel and view the ESP32-CAM playlist here:


Here’s a list of resources that I used to get this working: – Arduino Camera Web Server example – Homepage for the face recognition library

70 Replies to “Ai-Thinker ESP32-CAM in the Arduino IDE”

  1. Chris Lidyard says:

    Thanks for the article. Sorted me out and have donated. Keep posting, I’m interested in your adventures with the MAIX board.

    1. WordBot says:

      That’s great thanks! The MAIX is very interesting but they have a way to go to get to where the Espressif boards are with libraries etc.

  2. who_took_my_nick says:

    Brownout detector was triggered

    ets Jun 8 2016 00:22:57

    rst:0xc (SW_CPU_RESET),boot:0x1b (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    mode:DIO, clock div:1
    entry 0x400806a4

    It is power issue, as i can see from the forums. I power it as you suggested. From the same TTL adapter i use 5V and GND and connect it to 5V and GND on the ESP32 cam board. ESP module is little bit hot. Not sure is it ok. Any idea?

    1. WordBot says:

      I found that with the FT232RL connected with a USB cable that when the wifi started up it would crash with the brown out error. The other connector I plugged straight into my PC (no cable) and this was fine. It could be your adaptor or the USB cable that can’t carry the current needed. You can connect your own supply of 5v to the board (without the 5v and ground of the connector being connected) to see if that works.

      1. Richard D Marbury says:

        i got this device to work by connecting a 1000 ufd capacitor across 5v and gnd pins to reduce brownout errors

  3. _rp_ says:

    Thanks for this…

    Any ideas on how to activate the flash light?


    1. WordBot says:

      Not yet. I’ll write a note if I find out.

      1. Piebe says:

        GPIO4 is the Flash

        1. _rp_ says:

          That thing is bright…

  4. victor says:

    Do you have an example of how to save a photo to the card?

    1. WordBot says:

      Here’s a start – but this is for the Espressif IDF. I’ve not tried it myself.

  5. Richard Luckman says:

    Just in case anyone has the same problem that I had whereby the module worked fine plugged directly into the PC but as soon as I moved it to photograph the bird table just outside the window I lost connection. On my module the jumper next to the IPEX connector was set to use the IPEX connector and not the circuit board antenna. Pictures I have seen on the web show it jumpered the other way. As it happened my eventual plan was to use it with an external antenna so it saved me having to alter the jumper

    1. Tony Yeung says:

      Can you provide details of how the jumper is supposed to be configured? I can’t find the information of how to set it to IPEX versus PCB antenna.

  6. Ian Muir says:

    After booting and watching the serial monitor mine just shows dots going across the screen and nothing else.
    I am running off a seperate 5v power supply.
    any Ideas?

    1. WordBot says:

      The dots are shown while it’s trying to connect to the your wifi network. Double check your wifi settings and maybe move closer to the router.

      Also – see this comment:

      1. Ian Muir says:

        It now connects and I can log on to it with a web browser.
        There is no camera picture, the controls show but the camera picture is just black.

        1. WordBot says:

          Press f12 in the browser to open the console. Go to the network tab and then click Get Still or Start Stream on the controls do you see an error in the network tab?

          1. Ian Muir says:

            No errors, it just records a black screen. Tried 2 units both with the same results.

            1. WordBot says:

              I have another tutorial to finish this week that uses the camera in a different way. We can see if it works with this.

  7. Leszek Niedziela says:

    Thank you for the detailed explanation! Have a coffee! 🙂

    1. WordBot says:

      Appreciated! Thanks.

  8. Clavier pierre says:

    Merci pour ce tuto il fonctionne parfaitement. J’ai passé des jours à fouiller internet sans jamais réussir à faire fonctionner esp32cam encore un grand merci. Serait-il possible de connecter le module directement sur un écran tft lcd?

    1. WordBot says:

      It’s going to be difficult to connect a screen to the Ai-thinker board because nearly all the pins are used by the camera or SD-card reader (scroll down).

    2. Clavier pierre says:

      Re bonjour je viens de trouver et tester ce projet intéressant :G6EJD :ESP32-and-how-to-use-ili9341-TFT-Display. (sur Github) quand pensez-vous ?peut-être que comme ça l’image de la caméra pourrais apparaître sur l’écran ?

  9. Mike says:

    Thank you very much for this, three ESP32-Cams are now working smooth within my HomeAssistant / MotionEye – wonderful 😉
    After each reconnect of the ESP32-Cam to power, i have to press this little reset button once, for connecting to the WLAN – is there a pin layout to solder a bigger button to the Cam?
    So again, thank you very much for this!!!

    1. WordBot says:

      I just tried with mine and reconnecting power (at least via USB) causes it to reconnect to the WiFi.

  10. day tripper says:

    Thanks very much for this publication, I received a pair of the esp32-cam modules yesterday and had them both running by this afternoon.

    The one question I have is if anyone has integrated control of the hella bright LED into this kit? It doesn’t appear to be “wired” into the code (though I did notice it tends to have a weak glow).

    fwiw, I strongly recommend fitting some kind of heat sink to the SOC shield (and hope there’s some thermal compound under it) as it runs pretty toasty while streaming.


  11. Michael Zwicky-Ross says:

    Great tutorial. Except… I have the same problem as Ian Muir in that the ESP never connects to WiFi. I’ve checked and double checked the credentials and I’ve also flashed another sketch that I know works because I have it running on a basic ESP32. And the router is only 6 feet away. Any other ideas very welcome! Thank you

    1. WordBot says:

      Can you see how the tiny connector next the aerial socket is soldered?

      1. joe mckee says:

        Most of them come IPEX enabled , i have 10 and they are all the same – small jumper needs to be removed and soldered to internal aerial or an IPEX 2.4ghz aerial fitted

  12. Faiz Alfaizin says:

    can you help me with the problem “A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header”

    1. WordBot says:

      Is IO0 connected to GND? Try pressing the reset button and uploading the Sketch again.

  13. Faiz Alfaizin says:

    Can you help me.
    I have successfully uploaded a sketch and can switch to the web server. but the video played has a delay. when I put IO4 in my hand, the flash light went on and the video went smoothly without delay, could it be possible that the cable I used was wrong or was there a way for the video to run optimally without touching IO4?
    thank you

    1. WordBot says:

      Do you mean the frame-rate of the video is low? It’s possible the LED is making the scene brighter so the camera quality is improved. Try using a bright light on your subject.

      1. Faiz Alfaizin says:

        in the serial monitor “MJPG: 5173B 76ms (13.2fps), AVG: 101ms (9.9fps), 0+0+0+0=0 0”

        if i touch the IO4 pin “5173B 76ms (13.2fps)” change to be faster and read serial monitor

        does the IO4 pin affect fps?

        1. WordBot says:

          I don’t see how it could affect the fps

        2. Jim says:

          I also found that the framerate improved from around 2fps to 13fps (!) when I put my hand near the board. I then realised that (as others have found) the onboard antenna was not connected. Jumpering the onboard antenna cured the problem, and I now get a consistent good framerate 🙂

          1. WordBot says:

            Ah! Thanks for the comment. I didn’t imagine that this could be the problem!

            I looked at the cameras I have and found one was jumpered for the IPEX connector so I’ve added a bit explaining this to the tutorial.

  14. Minde says:

    Thanks a lot for a great tutorial, works like a charm. However I would like to change Camera Web Server ports (originally 80 and 81) and I am unable to find how to do it… Could You help?

    1. WordBot says:

      You can change the port number in the Arduino code in the function startCameraServer but you also have to change it in the HTML that the ESP32 is serving (here: j.src = `${c+’:81′}/stream`). This HTML is found in the camera_index.h file in the index_html_gz variable. This is the page source GZIP’d and converted to HEX. I have a tutorial in the works for this.

      UPDATE: Tutorial here:

  15. Jacques says:

    Thanks for a great tutorial, but get the same problem as Ian Muir. There is no camera picture, just the close icon and the controls.
    Can anyone help?

    1. WordBot says:

      Do you see any errors in the serial monitor or in the browser console? I have three of these and one of them came with a broken camera where there also was no image.

      1. Jacques says:

        I am seeing a pending status on the stream and image capture commands when pressed. This is under the network tab.

        1. WordBot says:

          What can you see in the Serial Monitor (Tools > Serial Monitor). Any clues there?

  16. Faiz Alfaizin says:

    can you help me for esp32-cam web socket ?

  17. Faiz Alfaizin says:

    I mean, so that the esp32-cam ip can be accessed by the internet with a public network

    1. Jim says:

      You should first change the camera ports from 80 and 81 to something higher like eg 8802 8804 as explained in a previous comment above. Then you need to set a couple of port forward entries in your router. EG if your camera IP is then add a couple of forward entries – port 8802 > and port 8804 >

      Then from the internet you should be able to access your camera by going to
      Note that here is you external IP address and can be found by going to Note that this address may change each time your router is rebooted.

      1. Jim says:

        Oops!- part of my text went a bit strange. It should have said;

        Then from the internet you should be able to access your camera by going to
        http://'your public IP address’:8802
        Note that ‘your public IP address’ here is your external IP address and can be found by going to Note that this address may change each time your router is rebooted.

  18. Jan-Gerard says:

    _Trigger events (pin I/O) with face recognition without web-interface?_
    Great tutorial. It workded directly. Only I want to take it a step further.
    I am looking for examples or documentation of the face recognition API to trigger events (like switching I/O pins of the ESP32-CAM board). Especially without using the web-interface. I would like to only use the web interface to train the recognition, but then just power the ESP32, have it start face recognition automatically, and respond by switching a voltage on one of the IO pins.
    Is that possible? And where do I find which commands to use for that?

    1. WordBot says:

      I’ll try to work out something this week for setting a pin high when a face is detected.

      1. WordBot says:

        I’ve added a new tutorial that explains how to do this:

  19. Petrovjan says:

    Hi, I’d like to turn the web-server example into a standalone presence detector, that would send a message to IFTTT whenever it detect someone. So far I’ve managed to update the Arduino IDE example and add the IFTTT call, but I’m not able to make it run all the time, not just when someone is accessing the ESP-CAM’s website.
    Is there a simple way to change the code to make it run all the time? Thanks!

    1. WordBot says:

      I need to look at the example code and see if I can work out how to make the face detection work outside of the web-server example. Hopefully this week.

      1. WordBot says:

        I’ve worked it out and written another tutorial for face recognition. If you want face detection only it should be pretty simple to modify.

  20. O-Zone says:

    Thanks a lot for your post! However, on compiling i got an error because the sketch use 106% of available space. Any hint how to fix?

    1. WordBot says:

      Do you have the partition scheme set to ‘Huge APP’ in the tools menu?

  21. Henk says:

    Arduino say the sketch is to big for the ESP32 CAM module. 172%. What to do now?

    In Dutch:
    De schets gebruikt 2257451 bytes (172%) programma-opslagruimte. Maximum is 1310720 bytes.
    Globale variabelen gebruiken 51488 bytes (15%) van het dynamisch geheugen. Resteren 276192 bytes voor lokale variabelen. Maximum is 327680 bytes.

    1. WordBot says:

      You should change the partition scheme to like this:

  22. Francis says:

    Hey! Thanks for this tutorial.

    From my understanding the HTML GetStill button tells the camera to push a jpeg to the server.

    How can I do this directly from my loop on the Esp32 ? (Eg. Just call GetStill(); in code instead of clicking the button on the webapp.

    1. WordBot says:

      Hi, Did you want to take a picture at a certain interval or as a result of some other input? It’s probably better to rewrite the code so your interval or input testing is in the loop and this then calls a function that grabs an image from the camera. You could also modify the HTML side of things to call GetStill and then do something with the resulting jpg.

      1. Francis says:

        Thanks for your reply.

        I am quite familiar with C/C++ – Not so much with html / http requests. I will be able to handle the interval at which the code is executed etc.

        Currently when the GetStill button is clicked, the image in the webapp changes to the latest screen capture. This functionality suits me and I would like to be able to do that without clicking but rather from the ESP32’s void loop. Some sensor will eventually trigger this functionality rather than a button press.

        1. WordBot says:

          I’m working on a tutorial for this.. It should be published today.

          1. Francis says:

            Awesome! Will be buying you a few more coffee’s for that! Thank you for your time.

            1. WordBot says:

              It’s taking a bit longer than I thought. It’s nearly done except

              esp_http_client_handle_t client = esp_http_client_init(&config);

              from here:

              Crashes in the Arduino. I’ll look for another method to POST images.

              1. Francis says:

                No problem! Thank you so much, helping my little brother out with his arduino project. I am a C++ programmer by trade though, so maybe I can help find the source of the crash on my side; I’ll give that example code a try!

                I’m just suprised this isn’t just a series of already available functions we need to combine as the functionality seems to be there by default. In any case thanks again, more well deserved coffees for you!

                1. WordBot says:

                  If you want to look I set up a simple example – crashes at esp_http_client_init
                  Guru Meditation Error: Core 1 panic’ed (LoadProhibited). Exception was unhandled.

  23. Kingtech says:

    Hi, I read all post but nobody seems to have a camera error. Maybe my camera is defective.
    Someone solved this kind of issues?

    1. WordBot says:

      IF you see a camera error in the serial monitor it could be defective. Have you tried removing it and replacing it? It could also be a power issue. What error message do you see?

      1. Kingtech says:

        Yes i try to removing and replacing it.
        Here the error message:
        12:49:38.464 -> ets Jun 8 2016 00:22:57
        12:49:38.464 ->
        12:49:38.464 -> rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
        12:49:38.464 -> configsip: 0, SPIWP:0xee
        12:49:38.464 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
        12:49:38.464 -> mode:DIO, clock div:1
        12:49:38.464 -> load:0x3fff0018,len:4
        12:49:38.464 -> load:0x3fff001c,len:1100
        12:49:38.464 -> load:0x40078000,len:10088
        12:49:38.464 -> load:0x40080400,len:6380
        12:49:38.464 -> entry 0x400806a4
        12:49:40.467 ->
        12:49:40.670 -> [E][camera.c:1085] esp_camera_init(): Camera probe failed with error 0x20001
        12:49:40.670 -> Camera init failed with error 0x20001

        I do somes research it seem that others than me have this kind of issue

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

scroll to top