Mandelbrot Set Fractal in Python
Render the Mandelbrot set in Python with NumPy and Matplotlib. Vectorized fractal generation, deep zooms, and Julia sets — runnable in your browser.
Try it yourself
Run this code directly in your browser. Click "Open in full editor" to experiment further.
Click Run to see output
Or press Ctrl + Enter
How it works
The Mandelbrot set is one of the most famous objects in mathematics. It's also one of the most surprising — an entire universe of infinite, self-similar detail emerges from a formula so simple you can write it on a sticky note: z = z² + c.
What The Mandelbrot Set Actually Is
Pick any complex number c. Then run this loop:
z = 0
repeat:
z = z*z + cOne of two things will happen:
c is not in the Mandelbrot set.c is in the Mandelbrot set.If you check every point in the complex plane and color the "in" points black, you get the iconic Mandelbrot silhouette: a heart-shaped main body with a circle bulb stuck to the left, surrounded by progressively smaller copies of itself.
The colorful halo around it isn't part of the set — it's a visualization of how fast each outside point escaped. Points that escape after 2 iterations get one color, points that take 200 iterations get another. That escape speed is what creates the fractal's shimmering, infinitely detailed boundary.
The One Mathematical Shortcut You Need
There's a beautiful theorem hiding here: if `|z|` ever exceeds 2, the sequence is guaranteed to escape to infinity. So you don't have to wait forever to know a point is outside the set — the moment |z| > 2, you can stop iterating and record the count. This is what max_iter is for: a budget. If a point hasn't escaped within that budget, we treat it as "in" the set.
Why You Vectorize With NumPy
The naive way to render this is a triple loop: for each pixel row, for each column, run the iteration loop. For a 600×600 image with 200 iterations, that's 72 million Python-level operations — agonizingly slow.
The NumPy version in the snippet does the same math, but on the entire grid at once. Z = Z**2 + C updates 360,000 complex numbers in a single CPU-friendly operation. The result is hundreds of times faster.
A few details that make the vectorized version work:
x[np.newaxis, :] + 1j * y[:, np.newaxis] builds the whole 2D grid of complex numbers in one expression using broadcasting.Z[alive] = Z[alive] ** 2 + C[alive] only updates the pixels that haven't escaped yet — once a pixel escapes, there's no point doing more math on it.alive &= ~escaped_now keeps a running boolean mask of which pixels are still being iterated.if not alive.any(): break catches the case where the entire image has escaped (common when zoomed far outside the set).Choosing `max_iter` — The Trade-off
Low max_iter is fast but loses detail near the boundary — points that would escape eventually get incorrectly classified as "in the set". High max_iter reveals more of the fractal's intricate edge but costs proportionally more computation.
A practical rule:
Where To Zoom
The boundary of the set is where the magic lives. A few famous neighborhoods worth visiting:
(-0.75, 0.1). Spirals everywhere.(0.275, 0). Look for trunks.(-1.75, 0).The deeper you zoom, the more bizarre the structures get. The set is provably self-similar at every scale — there is no "bottom" to reach.
Color Palettes Matter
The escape-iteration map is just integers. The visual character comes entirely from the colormap:
'twilight_shifted' — soft, dreamlike'inferno' / 'magma' — fiery, dramatic'twilight' — purple/cyan, very modern'hot' — high-contrast classic'gnuplot2' — psychedelicFor a really polished look, use smooth coloring: iter + 1 - log(log(|z|)) / log(2) instead of integer iteration counts. It eliminates the visible "banding" in the colors.
Julia Sets — The Same Idea, Inside Out
The Mandelbrot set lives in parameter space — each pixel is a different value of c. Julia sets live in dynamical space — c is fixed, and each pixel is a different starting z.
Every c in the complex plane has its own Julia set. Pick c from inside the Mandelbrot set and the Julia set is a connected blob. Pick c from outside and it shatters into a Cantor-like dust. The boundary points of the Mandelbrot set produce the most beautiful Julia sets — fractal swirls, lightning, and dragons.
A few c values that produce iconic Julia sets:
c = -0.7 + 0.27015i — a lacy, dragon-like shapec = -0.8 + 0.156i — flowing tendrilsc = 0.285 + 0.01i — crystalline spiralsc = -0.4 + 0.6i — "the seahorse"Things To Try Next
Run the snippet above and you'll see the full set in moments, dive into a region of detail that didn't even exist at the previous zoom level, and watch four Julia sets emerge from the same algorithm just by changing one constant.
Related examples
Fourier Transform (FFT) in Python
Learn the Fast Fourier Transform in Python. Decompose signals into frequencies with numpy.fft, plot the spectrum, and filter noise — all runnable in your browser.
NumPy Array Operations in Python
Learn NumPy basics in Python! A fun and easy guide to super-fast arrays, matrices, and data science math without using slow for-loops.
Matplotlib 3D Plot in Python
Create stunning 3D plots in Python with Matplotlib! Learn 3D surface, scatter, wireframe, and contour plots with runnable code — no setup required.