How to plot a circle in Python

Learn how to plot a circle in Python. This guide covers various methods, tips, real-world applications, and debugging common errors.

How to plot a circle in Python
Published on: 
Wed
Mar 25, 2026
Updated on: 
Thu
Mar 26, 2026
The Replit Team

To plot a circle in Python is a common task in data visualization, computer graphics, and simulations. Libraries like Matplotlib offer simple functions like plt.Circle() to create circles with precise control.

In this article, we'll cover several techniques to plot circles. You'll find practical tips, see real-world applications, and get advice to debug common issues, so you can master this essential skill.

Basic circle using matplotlib

import matplotlib.pyplot as plt
import numpy as np

theta = np.linspace(0, 2*np.pi, 100)
r = 5
x = r * np.cos(theta)
y = r * np.sin(theta)
plt.plot(x, y)
plt.axis('equal')
plt.show()--OUTPUT--[A circular plot with radius 5 centered at the origin]

This method plots a circle by calculating its coordinates using basic trigonometry. The code generates a series of angles from 0 to 2*np.pi radians—a full circle—using NumPy's linspace function. It then applies the parametric equations x = r * np.cos(theta) and y = r * np.sin(theta) to convert these angles into (x, y) points on the circle's circumference.

The call to plt.axis('equal') is essential. This function ensures the plot's aspect ratio is square, preventing the circle from being distorted into an ellipse due to automatic axis scaling.

Alternative plotting methods

Beyond calculating points with trigonometry, you can also plot circles using specialized tools like Matplotlib’s Circle patch or by defining their implicit equations with contour.

Using Circle patch in matplotlib

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
circle = Circle((0, 0), radius=5, fill=False)
ax.add_patch(circle)
ax.set_aspect('equal')
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()--OUTPUT--[An unfilled circle with radius 5 centered at the origin]

Matplotlib’s patches module offers a more object-oriented way to draw shapes. Instead of plotting hundreds of individual points, you can define a Circle object directly. This approach is often cleaner and more intuitive, treating the circle as a single entity.

  • First, you create a Circle instance, specifying its center coordinates and radius.
  • Setting fill=False makes the circle an outline rather than a solid shape.
  • Finally, you add this shape—known as a patch in Matplotlib—to your axes using the ax.add_patch() method.

Using implicit equation with contour

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-6, 6, 1000)
y = np.linspace(-6, 6, 1000)
X, Y = np.meshgrid(x, y)
F = X**2 + Y**2 - 25 # Circle equation: x² + y² = r²
plt.contour(X, Y, F, [0])
plt.axis('equal')
plt.show()--OUTPUT--[A circle plot created using the contour method]

This method leverages a circle's implicit equation, x² + y² - r² = 0. It's a clever way to define a shape without calculating individual points along its edge.

  • First, np.meshgrid generates a 2D coordinate grid from your x and y ranges.
  • The equation F = X**2 + Y**2 - 25 is then evaluated at every single point on this grid.
  • Finally, plt.contour(X, Y, F, [0]) draws the line connecting all points where the function's value is exactly zero, which perfectly traces the circle.

Creating a filled circle with plt.Circle

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
circle = plt.Circle((0, 0), 5, color='blue', alpha=0.5)
ax.add_artist(circle)
ax.set_aspect('equal')
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()--OUTPUT--[A semi-transparent blue filled circle]

It's straightforward to create a filled circle using plt.Circle. This function returns a circle object that is solid by default, and you can easily style its appearance with a few key arguments.

  • The color parameter sets the fill color, which is 'blue' in this example.
  • alpha controls the object's transparency. A value of 0.5 makes the circle semi-transparent.

Once you've defined the circle, you add it to your axes using the ax.add_artist() method, making it visible on the plot.

Advanced circle visualization

Building on these foundational techniques, you can create more dynamic visualizations, such as interactive circles with plotly, concentric patterns, and even 3D spheres.

Interactive circle with plotly

import plotly.graph_objects as go
import numpy as np

theta = np.linspace(0, 2*np.pi, 100)
x = 5 * np.cos(theta)
y = 5 * np.sin(theta)

fig = go.Figure(go.Scatter(x=x, y=y, mode='lines'))
fig.update_layout(yaxis=dict(scaleanchor="x", scaleratio=1))
fig.show()--OUTPUT--[An interactive circle plot that allows zooming and panning]

For interactive visualizations, plotly is an excellent tool. The code plots the circle's points using go.Scatter and connects them by setting mode='lines'. Unlike static Matplotlib plots, the output is a dynamic chart that allows users to zoom and pan, which is ideal for data exploration.

  • The fig.update_layout() method is essential for correct scaling.
  • By setting scaleanchor="x" and scaleratio=1, you ensure the y-axis maintains the same scale as the x-axis. This preserves the 1:1 aspect ratio, preventing the circle from appearing distorted.

Multiple concentric circles

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
for r in range(1, 6):
circle = Circle((0, 0), r, fill=False, color=f'C{r-1}')
ax.add_patch(circle)
ax.set_aspect('equal')
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()--OUTPUT--[Five concentric circles with different colors and increasing radii]

You can easily generate concentric circles by placing the Circle patch creation inside a loop. This code iterates five times, drawing a new circle with an increasing radius in each pass. Because every circle is drawn from the same center point (0, 0), the final result is a nested pattern.

  • The loop variable r directly controls the radius of each circle, starting from 1 and growing to 5.
  • The color is dynamically assigned using f'C{r-1}', which selects a distinct color from Matplotlib's default style cycle for each new circle.

3D sphere visualization

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = 5 * np.cos(u) * np.sin(v)
y = 5 * np.sin(u) * np.sin(v)
z = 5 * np.cos(v)
ax.plot_wireframe(x, y, z)
plt.show()--OUTPUT--[A 3D wireframe sphere with radius 5]

Extending a circle into three dimensions to create a sphere is a natural next step. This technique uses Matplotlib’s 3D toolkit, which you enable by setting projection='3d' when creating a subplot.

  • First, np.mgrid generates a grid of spherical coordinates—think of them as longitude and latitude lines.
  • These coordinates are then converted into Cartesian (x, y, z) points using standard parametric equations.
  • Finally, the ax.plot_wireframe() function connects these points to render the sphere's surface as a wireframe mesh.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. You describe what you want to build, and its AI capabilities help bring your idea to life.

With Replit Agent, you can turn the plotting concepts from this article into production-ready tools. The agent builds complete apps—with databases, APIs, and deployment—directly from your descriptions.

  • Build a signal strength visualizer that plots concentric circles to represent coverage areas, similar to the Circle patch examples.
  • Create an interactive geometry calculator where users can input a radius and center point to see a circle drawn instantly.
  • Deploy a data dashboard that uses circular markers to represent clusters, leveraging the interactive capabilities of libraries like plotly.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all within your browser.

Common errors and challenges

Plotting circles can sometimes lead to distorted shapes or jagged lines, but these common issues are usually simple to diagnose and fix.

A circle appearing as an ellipse is a classic sign that your plot's aspect ratio is off. This happens because Matplotlib scales axes independently by default. You can fix it by enforcing a square aspect ratio with plt.axis('equal') or ax.set_aspect('equal'), which guarantees your circle won't look stretched.

If your circle looks more like a polygon, you likely haven't defined it with enough points. When using trigonometric methods, the curve's smoothness is tied to the number of points generated by a function like np.linspace. The fix is simple—just increase the number of points to create a smoother, more circular shape.

It's also possible for a circle to be hidden behind other plot elements, even with correct code. Every object on a plot has a stacking order, which you can control with the zorder parameter. By giving your circle a higher zorder value, you tell Matplotlib to draw it on top of other elements, making it visible.

Fixing distorted circles when aspect is not set

When your figure's dimensions aren't equal, Matplotlib's default scaling can make your circle look like an oval. This distortion is a frequent issue, especially when you define a non-square figure size like figsize=(10, 5). See what happens in the code below.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots(figsize=(10, 5)) # Non-square figure
circle = Circle((0, 0), radius=5, fill=False)
ax.add_patch(circle)
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()

The figure's rectangular shape, defined by figsize, stretches the axes and distorts the circle. The code below shows how to lock the aspect ratio to resolve this.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots(figsize=(10, 5)) # Non-square figure
circle = Circle((0, 0), radius=5, fill=False)
ax.add_patch(circle)
ax.set_aspect('equal') # Fix: Set equal aspect ratio
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()

The solution is adding ax.set_aspect('equal'), which forces the axes to the same scale. This guarantees your circle won't be distorted, even when the figure's dimensions are rectangular from using figsize. It’s a common issue to watch for whenever your plot area isn't perfectly square. Without this command, the axes scale independently, stretching your circle into an oval.

Troubleshooting jagged circles with insufficient linspace points

Ever plotted a circle and had it come out looking more like a stop sign? This happens when you don't define enough points for the curve. Using too few points with np.linspace results in a jagged shape. The code below shows this effect.

import matplotlib.pyplot as plt
import numpy as np

theta = np.linspace(0, 2*np.pi, 12) # Too few points
r = 5
x = r * np.cos(theta)
y = r * np.sin(theta)
plt.plot(x, y)
plt.axis('equal')
plt.show()

With only 12 points generated by np.linspace, the plt.plot function connects them with straight lines, creating a polygon instead of a smooth curve. The corrected code below shows how to resolve this.

import matplotlib.pyplot as plt
import numpy as np

theta = np.linspace(0, 2*np.pi, 100) # More points for smoother circle
r = 5
x = r * np.cos(theta)
y = r * np.sin(theta)
plt.plot(x, y)
plt.axis('equal')
plt.show()

The solution is to generate more points for the curve. By increasing the value in np.linspace from 12 to 100, you create a denser set of coordinates. The plt.plot function connects these points with straight lines, so having more points results in shorter, less noticeable segments. This simple change transforms the jagged polygon into a smooth circle. Keep an eye on this whenever you're defining shapes with a series of points.

Resolving circle visibility issues with the zorder parameter

Sometimes your circle might be hidden behind other plot elements, like grid lines. This happens because Matplotlib draws objects in a specific order. You can control this stacking order using the zorder parameter to bring your circle to the front.

The code below shows a common scenario where a filled circle is partially obscured by the default grid.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
ax.grid(True)
circle = Circle((0, 0), radius=5, fill=True, color='lightblue')
ax.add_patch(circle)
ax.set_aspect('equal')
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()

Because Matplotlib draws grid lines on a layer above patches by default, the grid appears to slice through the filled circle. The code below shows how to adjust the stacking order to bring the circle forward.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
ax.grid(True)
circle = Circle((0, 0), radius=5, fill=True, color='lightblue', zorder=3)
ax.add_patch(circle)
ax.set_aspect('equal')
plt.xlim(-6, 6)
plt.ylim(-6, 6)
plt.show()

The solution is to assign a higher stacking order to the circle with the zorder parameter. By setting zorder=3, you tell Matplotlib to draw the circle on a layer above the grid lines, which have a lower default value. This ensures your shape isn't hidden. Keep an eye on zorder whenever plot elements overlap or one seems to disappear behind another; it’s a simple way to control which objects appear on top.

Real-world applications

Now that you can troubleshoot common plotting issues, you can build practical data visualizations like radar charts and custom gauges.

Creating a radar chart for data comparison

Radar charts are a clever application of polar coordinates, allowing you to map multiple data points onto a circular grid for quick, at-a-glance comparisons.

import matplotlib.pyplot as plt
import numpy as np

categories = ['Speed', 'Reliability', 'Usability', 'Price', 'Size']
values = [4, 4, 5, 3, 2]

angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False).tolist()
angles += angles[:1]
values += values[:1]

fig, ax = plt.subplots(subplot_kw=dict(polar=True))
ax.plot(angles, values)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(categories)
ax.fill(angles, values, alpha=0.1)
plt.show()

This code maps categorical data onto a polar plot. It begins by calculating evenly spaced angles for each category using np.linspace. The plot is a closed shape because the code appends the first angle and value to the end of their respective lists, connecting the last point back to the start.

  • The key is plt.subplots(subplot_kw=dict(polar=True)), which creates the circular grid instead of a standard x-y axis.
  • ax.plot draws the data's outline, while ax.fill colors the area inside for better visibility.

Building a simple gauge visualization with Wedge

You can build a custom gauge by combining Matplotlib’s Wedge patch for the background arc with a simple line plot to serve as the needle.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Wedge

fig, ax = plt.subplots(figsize=(6, 3))
ax.set_xlim(-1.1, 1.1)
ax.set_ylim(-0.6, 0.6)
ax.set_aspect('equal')

wedge = Wedge((0, 0), 0.5, 180, 0, width=0.1, color='lightgrey')
ax.add_patch(wedge)

value = 65
angle = np.radians(180 - (value/100 * 180))
ax.plot([0, 0.4*np.cos(angle)], [0, 0.4*np.sin(angle)], color='red', lw=2)

plt.axis('off')
plt.show()

This code constructs a gauge visualization in two parts. The Wedge patch creates the semi-circular background, and setting its width makes it a thin arc instead of a solid shape. The needle is a simple line drawn with ax.plot.

  • The code converts a value of 65 into a corresponding angle.
  • It then uses trigonometry to calculate the endpoint of the needle.

Finally, plt.axis('off') removes the x and y axes, giving the visualization a clean, focused look.

Get started with Replit

Turn these concepts into a real tool with Replit Agent. Try prompts like, “Build a radar chart generator from CSV data,” or, “Create a simple gauge visualization tool that accepts a percentage input.”

The agent writes the code, tests for errors, and deploys your app from a single prompt. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.