How to Set and Manage Window Size in Python Tkinter

Need a 640 by 360 pixel window? Call root.geometry("640x360") on your main window. That string sets the tkinter window size (width first, in pixels); an optional +x+y sets where it opens:

root = tk.Tk()
root.geometry("640x360+120+80")   # width x height + x + y

In this tutorial, I’ll size one small Expense Tracker window on Python 3.12.5 with Tk 8.6: reading, limiting, locking, centering and full screen.

Set the Tkinter window size and position with geometry()

Here’s the Expense Tracker main window. A label shows the size Tk actually gave it:

import tkinter as tk

root = tk.Tk()
root.title("Expense Tracker")
root.geometry("640x360+120+80")    # width x height + x + y

info = tk.Label(root, font=("Segoe UI", 14))
info.pack(expand=True)

def show_size():
    root.update()                  # let Tk apply the geometry first
    info.config(text=f"Size: {root.winfo_width()} x {root.winfo_height()}"
                     f"\ngeometry(): {root.geometry()}")

root.after(100, show_size)
root.mainloop()
Tkinter Expense Tracker window showing Size 640 x 360 and the geometry string 640x360+120+80
The window reports 640 x 360 pixels and 640x360+120+80, the same string that went into geometry().

The string format is "WIDTHxHEIGHT+X+Y" with a lowercase x and no spaces.

To size the widgets inside it, use a layout manager like the Tkinter pack geometry manager.

How do I get the current Tkinter window size?

Same window, read back. Call root.update() first, or Tk hasn’t drawn it yet:

import tkinter as tk

root = tk.Tk()
root.geometry("640x360")
print("Before update():", root.geometry(), root.winfo_width())

root.update()
print("After update(): ", root.geometry(), root.winfo_width())
print("Width x height: ", root.winfo_width(), "x", root.winfo_height())
root.destroy()

Output:

Before update(): 1x1+0+0 1
After update():  640x360+104+104 640
Width x height:  640 x 360

Before update(), geometry() said 1x1 and the width was 1. Afterward, both report the real 640 x 360 size.

winfo_width() and winfo_height() return integers. The same winfo_* family also gives you the mouse position in Tkinter.

Note: on a laptop with 125% display scaling, Python reports scaled (logical) pixels unless the app is DPI aware, so your numbers may not match a screenshot pixel for pixel.

Limit resizing with minsize() and maxsize()

Users drag window edges, so I set a floor and a ceiling. Same Expense Tracker, plus a button asking for 300 x 200:

import tkinter as tk

root = tk.Tk()
root.title("Expense Tracker")
root.geometry("640x360")
root.minsize(480, 300)             # smallest size allowed
root.maxsize(1000, 700)            # largest size allowed

info = tk.Label(root, font=("Segoe UI", 14))
info.pack(expand=True)

def show_size():
    root.update()
    info.config(text=f"Size: {root.winfo_width()} x {root.winfo_height()}")

def shrink():
    root.geometry("300x200")       # below minsize on purpose
    show_size()

tk.Button(root, text="Shrink to 300 x 200", command=shrink).pack(pady=12)
root.after(100, show_size)
root.mainloop()
Two Expense Tracker windows: before at 640 x 360 and after the Shrink button at 480 x 300, with the Size label boxed
Left: the starting 640 x 360 window. Right: after asking for 300 x 200, Tk stopped at 480 x 300.

minsize() doesn’t just stop mouse dragging; it also clamps geometry() calls from code. That’s why the window ended at 480 x 300, not 300 x 200.

Inside a resizable window, use sticky and weights so widgets stretch with it, as in this Tkinter Frame grid tutorial.

Make a fixed-size Tkinter window with resizable()

For a dialog-style window that should never change size, turn resizing off in both directions:

import tkinter as tk

root = tk.Tk()
root.title("Expense Tracker")
root.geometry("640x360")
root.resizable(False, False)       # (width, height)

tk.Label(root, text="Fixed-size window: 640 x 360",
         font=("Segoe UI", 14)).pack(expand=True)
root.mainloop()
Fixed-size Tkinter Expense Tracker window with the Maximize button grayed out in the title bar
With resizable(False, False) the 640 x 360 window can’t be dragged, and Windows grays out Maximize.

The two arguments are width and height, so resizable(True, False) allows horizontal resizing only. You can also restyle the frame with these Tkinter title bar color options.

Center a Tkinter window on the screen

Same Expense Tracker size. Subtract the window size from the screen size, halve it, then pass the offsets to geometry():

import tkinter as tk

root = tk.Tk()
root.title("Expense Tracker")
w, h = 640, 360
x = (root.winfo_screenwidth() - w) // 2
y = (root.winfo_screenheight() - h) // 2
root.geometry(f"{w}x{h}+{x}+{y}")
root.update()

print("Screen:", root.winfo_screenwidth(), "x", root.winfo_screenheight())
print("Placed at:", x, y)
print("geometry():", root.geometry())
root.destroy()

Output:

Screen: 1536 x 864
Placed at: 448 252
geometry(): 640x360+448+252
Command Prompt output showing the screen size, the computed offsets and the centered geometry string
The Command Prompt run: the window landed exactly at the computed offsets.

Integer division (//) keeps the offsets whole numbers, which geometry() requires.

Tk also has a built-in helper, but it centers the window’s requested size, not the size you set:

import tkinter as tk

root = tk.Tk()
root.geometry("640x360")
root.eval("tk::PlaceWindow . center")
root.update()
print("tk::PlaceWindow:", root.geometry())
root.destroy()

Output:

tk::PlaceWindow: 640x360+668+332

That landed off-center, so I stick with the math. Popups work the same way; see Tkinter multiple windows.

Open a Tkinter window maximized or full screen

On Windows, state("zoomed") maximizes the window and keeps the taskbar. attributes("-fullscreen", True) hides the title bar and covers the whole screen:

import tkinter as tk

root = tk.Tk()
root.geometry("640x360")

root.state("zoomed")               # maximized, taskbar visible
root.update()
print("state():", root.state())

root.state("normal")
root.attributes("-fullscreen", True)   # no title bar
root.update()
print("fullscreen:", root.attributes("-fullscreen"))
root.bind("<Escape>", lambda e: root.attributes("-fullscreen", False))
root.destroy()

Output:

state(): zoomed
fullscreen: 1

Bind Escape to leave full screen, since there’s no close button. On Linux (X11), use attributes("-zoomed", True) instead.

Common Tkinter window size errors and how to fix them

Two errors from building the Expense Tracker:

import tkinter as tk

root = tk.Tk()
for spec in ("640*360", "640x360"):
    try:
        root.geometry(spec)
        print(spec, "-> OK")
    except tk.TclError as err:
        print(spec, "-> TclError:", err)

root.maxsize(1000, 700)
try:
    root.attributes("-fullscreen", True)
except tk.TclError as err:
    print("fullscreen -> TclError:", err)
root.destroy()

Output:

640*360 -> TclError: bad geometry specifier "640*360"
640x360 -> OK
fullscreen -> TclError: can't set fullscreen attribute for ".": max width/height is too small

The first is a typo: geometry() needs a lowercase x. The second surprised me: a maxsize() smaller than the screen blocks full screen, so remove the limit first.

If you’re building a full app around this window, these come next:

Frequently asked questions

How do I set the window size in Tkinter?

Call root.geometry("640x360"). Width comes first, then height, in pixels.

How do I stop users from resizing a Tkinter window?

Call root.resizable(False, False), or allow a range with minsize()/maxsize().

How do I get the Tkinter window width and height?

Call root.update(), then read root.winfo_width() and root.winfo_height().

Why does geometry() return 1×1?

Tk hasn’t drawn the window yet. Call update() or update_idletasks() before reading it.

How do I make a Tkinter window full screen?

Use root.attributes("-fullscreen", True) and bind Escape to turn it off.

Where is geometry() documented?

See the tkinter page in the Python docs.