In this tutorial you will learn how to stream video from the ESP32 Camera Pro Kit over your local Wi-Fi network to your Web browser. We are essentially building a wireless surveillance camera that you can monitor from your computer.
Required Parts
For this project you will need the ESP32 Camera Pro Kit by SunFounder and a USB cable.

ESP32 Camera Pro Kit
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
SunFounder ESP32 Camera Pro Kit
The SunFounder ESP32 Camera Pro Kit provides a compact and feature-rich platform for developing wireless video streaming and embedded vision applications.
At its core is the ESP32 WROOM-32E module, a dual-core microcontroller integrating Wi-Fi and Bluetooth connectivity, paired with an OV2640 camera capable of capturing images up to 1600 × 1200 resolution.
The extension board included in the kit consolidates essential peripherals such as a micro-SD card slot, battery charging circuitry, GPIO expansion headers, and a 24-pin camera interface, offering both flexibility and reliability for prototyping and deployment.

The kit supports a single 18650 lithium-ion battery, enabling stand-alone operation without external power. Its combination of on-board storage, wireless networking, and camera functionality makes it well-suited for IoT scenarios such as remote monitoring, real-time streaming, and data logging.

Technical Specification
| Component / Feature | Specification |
|---|---|
| Microcontroller | ESP32 WROOM-32E, dual-core Xtensa® 32-bit LX6 @ up to 240 MHz |
| Wireless | Wi-Fi 802.11 b/g/n, Bluetooth 4.2 (BR/EDR + BLE) |
| Camera Module | OV2640, 2 MP sensor, up to 1600 × 1200 resolution, ~68° FOV |
| On-board Storage | Micro-SD card slot (supports up to 32 GB, FAT32) |
| Power Supply | 3.7 V 18650 Li-ion battery (USB rechargeable, onboard charge management) |
| Expansion Interfaces | Female GPIO headers, 14-pin screw terminal block (3.5 mm pitch) |
| Camera Interface | 24-pin FFC/FPC connector (dedicated for OV2640) |
| Indicators | Power (PWR) and charging (CHG) status LEDs |
| Programming Interfaces | Micro-USB (UART, power, charging) |
Pinout of ESP32 WROOM-32E

Installation of ESP32 Core
If this is your first project with a board of the ESP32 series, you will need to install the ESP32 core first. If ESP32 boards are already installed in your Arduino IDE, you can skip this section.
Start by opening the Preferences dialog by selecting “Preferences…” from the “File” menu. This will open the Preferences dialog shown below.
Under the Settings tab you will find an edit box at the bottom of the dialog that is labelled “Additional boards manager URLs“:

In this input field copy the following URL:
https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
This will let the Arduino IDE know, where to find the ESP32 core libraries. Next we will install the ESP32 boards using the Boards Manager.
Open the Boards Manager via “Tools -> Boards -> Board Manager”. You will see the Boards Manager appearing in the left Sidebar. Enter “ESP32” in the search field at the top and you should see two types of ESP32 boards; the “Arduino ESP32 Boards” and the “esp32 by Espressif” boards. We want the esp32 libraries by Espressif. Click on the INSTALL button and wait until the download and install is complete.

Selecting Board
Finally we need to select a ESP32 board. In case of the ESP32 Camera Pro Kit, we pick the generic “AI Thinker ESP32-CAM”. For that, click on the drop-down menu and then on “Select other board and port…”:

This will open a dialog where you can enter “ai” in the search bar. You will see the “AI Thinker ESP32-CAM” board under Boards. Click on it and the COM port to activate it and then click OK:

Alternatively, you could also select the newer “ESP32 Dev Module“, but in this case you have to enable PSRAM and Huge APP in the Tool menu.
Note that you need to connect the board via the USB cable to your computer, before you can select a COM port.
Streaming Video
In this project we are implementing a video streaming server that runs on the ESP32, which is the microprocessor built into the ESP32 Camera Pro Kit. The camera takes images and the ESP32 serves them over Wi-Fi. Your Wi-Fi router transports these images then to a Web Browser, which displays the images as a video stream. The picture below illustrates the setup:

Note that the video stream is not encrypted or secure but will be only visible at an URL within your local Wi-Fi network, e.g. 192.168.2.39/stream. Only someone with access to your Wi-Fi network will be able to see the video stream.
Code for Video Server
The following Arduino code implements the video streaming server that sends a continuous MJPEG stream from the ESP32 Camera Pro Kit to any web browser connected to the same Wi-Fi network.
We will use the esp32cam library, which makes the handling of the camera simpler. You can install it via the Library Manager in the Arduino IDE. Just search for “esp32cam” and press INSTALL. The picture below shows the completed installation:

Below is the complete code for the video streaming server. Have a quick look first and then we will go into its details:
#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"
const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/stream";
const auto RESOLUTION = esp32cam::Resolution::find(1024, 768);
WebServer server(80);
void handleStream() {
static char head[128];
WiFiClient client = server.client();
server.sendContent("HTTP/1.1 200 OK\r\n"
"Content-Type: multipart/x-mixed-replace; "
"boundary=frame\r\n\r\n");
while (client.connected()) {
auto frame = esp32cam::capture();
if (frame) {
sprintf(head,
"--frame\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %ul\r\n\r\n",
frame->size());
client.write(head, strlen(head));
frame->writeTo(client);
client.write("\r\n");
}
}
}
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RESOLUTION);
cfg.setBufferCount(2);
cfg.setJpeg(80);
Camera.begin(cfg);
}
void initWifi() {
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.printf("Stream at: http://%s%s\n",
WiFi.localIP().toString().c_str(), URL);
}
void initServer() {
server.on(URL, handleStream);
server.begin();
}
void setup() {
Serial.begin(115200);
initWifi();
initCamera();
initServer();
}
void loop() {
server.handleClient();
}
Includes
The code begins by including the necessary libraries:
#include "WebServer.h" #include "WiFi.h" #include "esp32cam.h"
These libraries enable HTTP server functionality (WebServer.h), Wi-Fi connectivity (WiFi.h), and camera control (esp32cam.h).
Constants
Next, we define a few constants:
const char* WIFI_SSID = "SSID"; const char* WIFI_PASS = "PASSWORD"; const char* URL = "/stream"; const auto RESOLUTION = esp32cam::Resolution::find(1024, 768);
The WIFI_SSID and WIFI_PASS variables store the credentials for the Wi-Fi network. You will have to replace SSID and PASSWORD with the actual login details for your Wi-Fi- network.
The URL is the path on which the video stream will be served. You can change this to anything you like. For instance, “/video” or “/frontdoor”, just make sure you keep the slash (‘/’) at the beginning.
The RESOLUTION sets the desired resolution for the camera using the esp32cam library.
Here is a list of the possible values for the camera resolution, though depending on the camera used not all of them may work:
- 96×96
- 160×120
- 128×128
- 176×144
- 240×176
- 240×240
- 320×240
- 320×320
- 400×296
- 480×320
- 640×480
- 800×600
- 1024×768
- 1280×720
- 1280×1024
- 1600×1200
You can print the list of camera resolutions using the following function:
void printResolutions() {
Serial.println("Camera resolutions:");
for (auto res : esp32cam::Camera.listResolutions()) {
Serial.printf("%dx%d\n", res.getWidth(), res.getHeight());
}
}
Note that the resolution will affect the maximum framerate. With a 1600×1200 resolution you will not get much more than 10 frames per second.
Objects
The following line creates an HTTP server object that listens on port 80. That is our web server that provides the video stream.
WebServer server(80);
handleStream
The function handleStream() handles the video stream whenever a client accesses the /stream path:
void handleStream() {
static char head[128];
WiFiClient client = server.client();
This line obtains the current client connected to the server. The response is then prepared:
server.sendContent("HTTP/1.1 200 OK\r\n"
"Content-Type: multipart/x-mixed-replace; "
"boundary=frame\r\n\r\n");
This header tells the browser that it will receive a multipart MJPEG stream, where each part is separated by a boundary called frame.
Inside a loop, the function captures a frame from the camera:
while (client.connected()) {
auto frame = esp32cam::capture();
If a frame is successfully captured, a header is constructed describing the JPEG image, and then sent to the client as a JPEG:
if (frame) {
sprintf(head,
"--frame\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %ul\r\n\r\n",
frame->size());
client.write(head, strlen(head));
frame->writeTo(client);
client.write("\r\n");
}
initCamera
The initCamera() function configures and starts the camera hardware:
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RESOLUTION);
cfg.setBufferCount(2);
cfg.setJpeg(80);
Camera.begin(cfg);
}
Here, a Config object is created. The setPins function configures the camera pins based on the AiThinker board layout, which works for the ESP32 Camera Pro Kit as well. setResolution defines the resolution to use, while setBufferCount determines how many image buffers are used internally.
The setJpeg function sets the JPEG compression quality. 80 is a good balance between quality and size. 90 gives you better quality but a smaller reduction in image size. For faster video you can reduce the resolution and the JPEG compression but obviously you will get smaller images with lower quality.
Finally, Camera.begin(cfg) initializes the camera with these settings.
initWifi
The initWifi() function connects the ESP32 to the specified Wi-Fi network:
void initWifi() {
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.printf("Stream at: http://%s%s\n",
WiFi.localIP().toString().c_str(), URL);
}
WiFi.persistent(false) disables writing the credentials to flash, which speeds up reconnection. The device is set to station mode (WIFI_STA), and it attempts to connect to the Wi-Fi using the given credentials.
Once connected, the IP address and stream path are printed to the serial monitor. You will need to copy and past this printer URL into your browsers address bar to see the video stream. The actual URL will depend on your ESP32″. In my case I see the following URL on the Serial Monitor:

Therefore, I copy “http://192.168.2.39/stream” into the address bar of my Chrome browser to access the video.
initServer
The initServer() function links the streaming path to the handler and starts the server:
void initServer() {
server.on(URL, handleStream);
server.begin();
}
This maps any request to /stream to the handleStream() function, and then starts the server.
setup
The setup() function runs once at boot:
void setup() {
Serial.begin(115200);
initWifi();
initCamera();
initServer();
}
It starts the serial communication, connects to Wi-Fi, initializes the camera, and sets up the web server.
loop
Finally, the loop() function continuously handles incoming HTTP requests:
void loop() {
server.handleClient();
}
This line allows the ESP32 to respond to client requests by invoking any registered handlers such as handleStream().
For flashing that code to your ESP32 module, make sure to select the AI Thinker ESP32-CAM board:

Conclusions
In this tutorial you learned how to stream video with ESP32 Camera Pro Kit over your local Wi-Fi network to your Web browser.
With the attached battery, charging support and the screw terminals on the extension board is very easy to build a battery-powered surveillance system without soldering. For instance, you could attach a flash light and a horn to sound an alarm when motion is detected. Have a look at our Motion Activated ESP32-CAM tutorial, for more information.
Note that the extension board of the ESP32 Camera Pro Kit is comparatively big. If you need a smaller board with a camera, you could use the XIAO-ESP32-S3-Sense. It is very small, however, if you want to connect additional hardware you need to know how to solder.
Once you have a video stream, you could also start to detect objects in the video. See our Object Detection with ESP32-CAM and YOLO tutorial. It is written for the ESP32-CAM but requires only a minimal change (cfg.setPins(pins::AiThinker)) to work with the ESP32 Camera Pro Kit.
Finally, have a look at SunFounders Wiki for the ESP32 Camera Pro Kit. You will find additional information and projects there.
If you have any questions, feel free to leave them in the comment section.
Happy Tinkering 😉
Stefan is a professional software developer and researcher. He has worked in robotics, bioinformatics, image/audio processing and education at Siemens, IBM and Google. He specializes in AI and machine learning and has a keen interest in DIY projects involving Arduino and 3D printing.

