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.

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
Circleinstance, specifying its center coordinates and radius. - Setting
fill=Falsemakes 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.meshgridgenerates a 2D coordinate grid from your x and y ranges. - The equation
F = X**2 + Y**2 - 25is 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
colorparameter sets the fill color, which is'blue'in this example. alphacontrols the object's transparency. A value of0.5makes 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"andscaleratio=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
rdirectly 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.mgridgenerates 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
Circlepatch 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.plotdraws the data's outline, whileax.fillcolors 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
valueof 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.
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.
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.

.png)
.png)
.png)