Raspberry Pi Pico W Onboard WiFi: CYW43439 Networking Without an ESP32
This site's Pico coverage — getting started with MicroPython, the Pico 2 and RP2350, Pico vs. Arduino — treats the Pico as a plain microcontroller board, and its networked projects almost always pair a Pico with a separate ESP32 for WiFi. That's the right call for the original Pico, which has no wireless silicon at all. But the Pico W (and Pico 2 W) has had onboard WiFi since 2022 via an Infineon CYW43439 chip on a small daughterboard-style module, wired to the RP2040 over SPI — and it's genuinely underused because so many tutorials still default to reaching for an ESP32 out of habit. This guide covers what's actually different about networking on a Pico W and how to get it running in both MicroPython and C/C++.
Why the Pico W Isn't "Just Add WiFi to an RP2040"
The CYW43439 isn't a peripheral you talk to over a simple UART or a driver-free bus the way the ESP32's WiFi radio is integrated into that chip's own silicon. On the Pico W, the RP2040 drives the CYW43439 over a bit-banged SPI-like interface (called "gspi") using three GPIO pins that are otherwise unavailable for general use on that board (GPIO 23, 24, 25, and 29 are reserved for the wireless chip and the onboard LED, which is itself wired through the wireless chip rather than a plain GPIO on the W variant — a genuinely confusing gotcha for anyone porting non-W Pico code that blinks the LED directly). All of this driver complexity is handled for you by the cyw43-driver library that ships with both the Pico SDK and MicroPython — you don't bit-bang anything yourself — but it's worth knowing this is a distinct radio module being driven over a dedicated bus, not silicon-integrated radio the way it is on an ESP32.
MicroPython: Fastest Path to a Connected Pico W
import network import time wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect('your-ssid', 'your-password') while not wlan.isconnected(): time.sleep(0.5) print('Connected, IP:', wlan.ifconfig()[0])From there, MicroPython's urequests or the built-in socket module let you do HTTP calls or raw TCP/UDP exactly as you would on an ESP32 running MicroPython — the networking API surface is intentionally similar across ports. The onboard LED, reserved on the wireless chip, is accessed slightly differently than a plain GPIO:
from machine import Pin led = Pin("LED", Pin.OUT) # note: not a plain integer pin number on Pico W led.toggle()C/C++ with the Pico SDK: lwIP and cyw43_arch
Native C development uses the lwIP TCP/IP stack (the same lightweight stack used across countless embedded platforms) glued to the wireless chip through the cyw43_arch library. There are two operating modes worth knowing about explicitly:
- Polling mode (cyw43_arch_init() + calling cyw43_arch_poll() regularly in your main loop) — simpler, appropriate for straightforward projects without an RTOS, but you must call the poll function often enough or networking stalls.
- Background/threadsafe mode (using the FreeRTOS-based background variant of the SDK's networking libraries) — runs the network stack on its own core or task, appropriate when your main application logic can't guarantee frequent polling calls.
What the Pico W Is (and Isn't) Good At
Good fitBetter served by ESP32 Simple sensor nodes posting to a server or MQTT brokerProjects also needing Bluetooth/BLE (Pico W has none; Pico 2 W adds BLE via the same CYW43439-family chip on some SKUs — check the specific module) Projects already committed to the RP2040's PIO peripheral for other I/O (the reason to pick a Pico over an ESP32 in the first place)Projects needing WiFi mesh, ESP-NOW, or the deep RTOS/task ecosystem this site's ESP32 content already covers extensively Learning raw lwIP/TCP-IP concepts without the abstraction layers Arduino-ESP32 addsAnything wanting Arduino-style library ecosystem breadth — ESP32's Arduino core has a much larger body of ready-made networking librariesCommon Pitfalls
- Reusing non-W Pico pinouts. Code and wiring diagrams written for a plain Pico that use GPIO 23, 24, or 25 for anything other than the wireless chip will not behave the same on a Pico W — those pins are reserved.
- Power draw during association. Wifi radios draw meaningfully more current during connection/association bursts than steady-state; a Pico W running from a marginal USB power source or a small battery regulator can brown out right when you least expect it — at connect time — if your supply isn't sized with headroom.
- Forgetting country/region settings. Both the SDK and MicroPython let you set a WiFi country code (affects allowed channels and transmit power); leaving it at a default that doesn't match your actual region can cause weak association or regulatory non-compliance depending on where you are.
- Expecting BLE on the plain Pico W. The original Pico W's CYW43439 variant is WiFi-only; only later Pico 2 W boards pair with a chip revision or companion that adds Bluetooth — verify before designing a project around both radios on one board.
The Pico W doesn't need an ESP32 riding shotgun to get online — its onboard WiFi is fully capable for straightforward connected projects, and reaching for the RP2040's excellent PIO peripheral and deterministic timing alongside genuine onboard networking, rather than defaulting to an ESP32 out of habit, is worth considering any time a project's I/O side benefits more from PIO than from the ESP32 ecosystem's breadth.
Related Guides
- Raspberry Pi Pico W
- Arduino vs ESP32: Which Should You Use? A Practical Comparison
- Getting Started with ESP32: GPIO, WiFi, and Your First Project
- Choosing a Wireless Protocol for Maker Projects: WiFi, Bluetooth, Zigbee, Z-Wave, LoRa, and Thread Compared
- ESPHome and Home Assistant Beginner Guide: Build Your First WiFi Sensor
- ESP32-WROOM-32
- Raspberry Pi Pico
- Raspberry Pi Pico 2 W