Beginner Project ยท Python Desktop App

Location-Based
Weather App
in Python.

A complete walkthrough of building a Location-Based Weather App in Python โ€” without any paid APIs. Use requests + BeautifulSoup to scrape the National Weather Service, Geopy for geocoding, and Tkinter for a clean desktop GUI. Every line of code is explained for beginners โ€” with copy buttons on every block.

๐ŸŒค๏ธLive weather data
0API keys needed
4Python libraries
1Desktop GUI
weather_app.py
# Weather App โ€” scrape weather.gov
import requests
from bs4 import BeautifulSoup

def fetch_weather_data(location):
    url = f"https://forecast.weather.gov/..."
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')
No API keyjust scraping
Copy & Runfull project code
Tkinter GUIdesktop interface
Step 01 / Tools & Requirements

The four tools
behind the weather app.

This project uses only free, open-source Python libraries. No paid APIs, no API keys, no credit cards.

๐Ÿง‘โ€๐Ÿซ Beginner’s Guide โ€” Before You Start

Hey there! If you’re just getting started with coding, you’re in for a fun ride. We’ll build a Location-Based Weather App using Python โ€” with complete control over the data and a deeper understanding of the mechanisms that power weather apps.

What you need installed:

  • Python โ†’ the language. Version 3.8 or newer.
  • requests โ†’ makes HTTP requests and fetches the weather page.
  • beautifulsoup4 โ†’ parses the HTML returned by the website so we can extract data.
  • geopy โ†’ converts a city name into latitude/longitude coordinates.
  • tkinter โ†’ ships with Python. Creates the desktop GUI.

Install everything in one command:

install.sh
# Install the three external libraries (tkinter ships with Python)
pip install requests beautifulsoup4 geopy
โžœ~/weather-apppip install requests beautifulsoup4 geopy
Successfully installed requests-2.31.0 Successfully installed beautifulsoup4-4.12.2 Successfully installed geopy-2.4.1
โœ“All dependencies ready โ€” let’s start coding
Why no API? Most weather APIs (OpenWeather, WeatherAPI) require a key, have rate limits, and a free tier that expires. The National Weather Service publishes public-domain data on a website โ€” we just have to read it. This is called web scraping.
Step 02 / Fetching Weather Data

Scrape weather.gov with requests + BeautifulSoup.

We’ll begin by scraping weather data from a reliable source. The National Weather Service is widely used for this purpose. We’ll identify the HTML elements that hold temperature, humidity, and current conditions.

๐Ÿง‘โ€๐Ÿซ Beginner’s Guide โ€” Web Scraping Basics

What is HTTP? When you type a URL into your browser, your browser sends an HTTP GET request to a server. The server responds with HTML โ€” the code that your browser turns into a webpage. The requests library lets Python do the same thing.

What is HTML? HTML is the language web pages are written in. It uses tags like <p> (paragraph), <img> (image), <div> (a block). Each tag can have a class attribute that we use to find specific elements.

What is BeautifulSoup? BeautifulSoup takes raw HTML and turns it into a tree of Python objects. Instead of writing fragile string searches, you can ask it: “find the <p> tag with class tombstone-container.” It makes scraping a breeze.

The URL pattern: The National Weather Service accepts a URL like https://forecast.weather.gov/MapClick.php?textField1=LAT,LON. We pass the latitude and longitude, and it returns the forecast for that exact point.

step2_fetch_weather.py
import requests
from bs4 import BeautifulSoup

def fetch_weather_data(location):
    # Construct the URL for the desired location
    # location is a "lat,lon" string returned by Geopy (Step 3)
    url = f"https://forecast.weather.gov/MapClick.php?textField1={location}"

    # Send an HTTP GET request
    response = requests.get(url)

    # Parse the HTML content of the page
    soup = BeautifulSoup(response.content, 'html.parser')

    # Extract the weather data
    temperature = soup.find("p", class_="tombstone-container").text
    humidity = soup.find("p", class_="period-name").find_next_sibling().text
    conditions = soup.find("img")["alt"]

    return temperature, humidity, conditions
โžœ~/weather-apppython -c “from step2_fetch_weather import fetch_weather_data; print(fetch_weather_data(‘40.7128,-74.0060’))”
(’72ยฐF’, ‘60%’, ‘Partly Cloudy’)โ† actual values depend on the live weather at that location
โœ“Weather fetched successfully โ€” scraped from weather.gov
๐Ÿ“– Code Walkthrough โ€” What Each Line Does
import requests
Lines 1โ€“2: Import the libraries. requests talks to the website, BeautifulSoup parses the HTML it returns.
url = f”…”
Line 6: Build the URL using an f-string. The {location} placeholder gets replaced with the latitude/longitude string.
requests.get(url)
Line 9: Send the HTTP GET request. The response object contains the HTML of the forecast page.
BeautifulSoup(…)
Line 12: Parse the raw HTML into a searchable tree. We use the built-in html.parser.
soup.find(“p”, class_=”tombstone-container”)
Line 15: Find the <p> tag with class tombstone-container โ€” that’s where weather.gov puts the temperature.
find_next_sibling().text
Line 16: Find the next sibling element after the period-name โ€” that’s where the humidity lives.
soup.find(“img”)[“alt”]
Line 17: The first <img> tag’s alt attribute describes the current conditions (e.g., “Partly Cloudy”).
Important: The class names (tombstone-container, period-name) are specific to weather.gov’s HTML structure. If the website changes its layout, these selectors will need to be updated. Visit the site and use your browser’s “Inspect Element” to verify.
Step 03 / Geocoding

Convert city names into coordinates.

Our app’s main feature is location-based weather, so we need to convert location names like “Paris” into latitude and longitude coordinates. Geopy makes this task a breeze.

๐Ÿง‘โ€๐Ÿซ Beginner’s Guide โ€” What is Geocoding?

Why do we need coordinates? The weather.gov URL expects a latitude and longitude โ€” not a city name. Try typing a city into the URL and it won’t work. So we need a translator: city name โ†’ coordinates. That translation is called geocoding.

What is Geopy? Geopy is a Python library that talks to free geocoding services. We’ll use Nominatim, the open-source geocoder powered by OpenStreetMap. It’s free and requires no API key (just a user-agent string).

What is a user-agent? Nominatim asks that you identify your app with a string like "weather-app". This helps them track usage and prevent abuse. Always set a descriptive user_agent.

What does geocode() return? A Location object with .latitude and .longitude attributes โ€” exactly what we need to build the weather.gov URL.

step3_geocode.py
from geopy.geocoders import Nominatim

def get_coordinates(location):
    geolocator = Nominatim(user_agent="weather-app")
    location = geolocator.geocode(location)
    return location.latitude, location.longitude
โžœ~/weather-apppython -c “from step3_geocode import get_coordinates; print(get_coordinates(‘New York’))”
(40.7127281, -74.0060262)โ† latitude, longitude of New York City
โœ“City name converted to coordinates
๐Ÿ“– Code Walkthrough โ€” Step by Step
from geopy.geocoders import Nominatim
Line 1: Import the Nominatim geocoder โ€” OpenStreetMap’s free geocoding service.
Nominatim(user_agent=”weather-app”)
Line 4: Create a geolocator object. The user_agent identifies your app to OpenStreetMap. Always set this.
geolocator.geocode(location)
Line 5: Send the city name to Nominatim. It returns a Location object with coordinates, address, and other metadata.
location.latitude, location.longitude
Line 6: Return the two coordinates as a tuple. These get passed into the weather.gov URL in Step 2.
Chaining it together: When the user types “New York” in the GUI, we’ll call get_coordinates("New York") โ†’ get (40.71, -74.00) โ†’ format as "40.71,-74.00" โ†’ pass to fetch_weather_data() from Step 2.
Step 04 / Building the GUI

A clean Tkinter interface
in 10 lines of code.

A user-friendly interface is crucial. Tkinter helps us create a simple yet effective GUI โ€” an entry field, a button, and a display area.

๐Ÿง‘โ€๐Ÿซ Beginner’s Guide โ€” Tkinter Basics

What is Tkinter? Tkinter is Python’s built-in GUI library. It comes with Python โ€” no pip install needed. It’s perfect for building small desktop apps like this weather tool.

The three widgets we’ll use:

  • tk.Label() โ†’ displays text (like “Enter Location:” or the weather results).
  • tk.Entry() โ†’ a single-line text input where the user types the city name.
  • tk.Button() โ†’ a clickable button. The command argument is the function that runs when clicked.

What is .pack()? Tkinter needs to know where to place each widget. .pack() is the simplest layout manager โ€” it stacks widgets vertically, top to bottom.

What is window.mainloop()? This starts the event loop โ€” it keeps the window open and listens for clicks and key presses. Without it, the window would flash and disappear instantly.

What is a lambda? The button’s command needs a function with no arguments. But we want to pass entry.get() (what the user typed). A lambda creates a tiny anonymous function that captures the entry value at click-time.

step4_gui.py
import tkinter as tk

def create_gui():
    window = tk.Tk()
    window.title("Location-Based Weather App")

    label = tk.Label(window, text="Enter Location:")
    label.pack()

    entry = tk.Entry(window)
    entry.pack()

    button = tk.Button(window, text="Get Weather", command=lambda: display_weather(entry.get()))
    button.pack()

    display = tk.Label(window, text="")
    display.pack()

    window.mainloop()
โžœ~/weather-apppython step4_gui.py
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Location-Based Weather App โ”‚ โ”‚ โ”‚ โ”‚ Enter Location: โ”‚ โ”‚ [ New York ] โ”‚ โ”‚ [ Get Weather ] โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ† a small desktop window opens โ€” type a city & click
โœ“Tkinter window launched โ€” waiting for user input
๐Ÿ“– Code Walkthrough โ€” Widget by Widget
tk.Tk()
Line 4: Create the main window. This is the container for all widgets.
window.title(“…”)
Line 5: Set the title bar text of the window.
tk.Label(window, text=”Enter Location:”)
Lines 7โ€“8: Create a label that says “Enter Location:” and place it in the window with .pack().
tk.Entry(window)
Lines 10โ€“11: Create a single-line text input field where the user types the city.
tk.Button(…, command=lambda: display_weather(entry.get()))
Lines 13โ€“14: Create the button. When clicked, the lambda reads the text from the entry and passes it to display_weather() โ€” defined in Step 5.
display = tk.Label(window, text=””)
Lines 16โ€“17: An empty label that we’ll later fill with the weather results.
window.mainloop()
Line 19: Start the event loop. The window stays open, listening for clicks, until the user closes it.
Step 05 / Displaying Weather

Format the results and add
weather icons.

Once we fetch the weather data, we need to present it to the user in a friendly format โ€” temperature, humidity, and conditions, plus an emoji icon for a visual touch.

๐Ÿง‘โ€๐Ÿซ Beginner’s Guide โ€” Output & Icons

Why format the output? The raw scraped strings can be messy โ€” extra whitespace, mixed case, weird characters. A clean format like "Temperature: 72ยฐF" is much easier to read.

Adding weather icons: We check the conditions string for keywords like “rain” or “sun” and print the matching emoji. This is a simple if / elif / else โ€” your first taste of conditional logic in a real app.

The display_weather() glue function: This connects the GUI button to the rest of the app. It calls get_coordinates(), formats the result, calls fetch_weather_data(), and finally calls display_weather_data().

step5_display.py
def display_weather(location):
    try:
        lat, lon = get_coordinates(location)
        coords = f"{lat},{lon}"
        temperature, humidity, conditions = fetch_weather_data(coords)
        display_weather_data(temperature, humidity, conditions)
    except Exception as e:
        print(f"Error: {e}")


def display_weather_data(temperature, humidity, conditions):
    print("Weather Information:")
    print(f"Temperature: {temperature}")
    print(f"Humidity: {humidity}")
    print(f"Conditions: {conditions}")

    # You can add weather icons here based on conditions
    if "rain" in conditions.lower():
        print("Weather Icon: ๐ŸŒง๏ธ")
    elif "sun" in conditions.lower():
        print("Weather Icon: โ˜€๏ธ")
    else:
        print("Weather Icon: ๐ŸŒค๏ธ")


# Example usage:
temperature = "72ยฐF"
humidity = "60%"
conditions = "Partly Cloudy"

display_weather_data(temperature, humidity, conditions)
โžœ~/weather-apppython step5_display.py
Weather Information: Temperature: 72ยฐF Humidity: 60% Conditions: Partly Cloudy Weather Icon: ๐ŸŒค๏ธ
โœ“Weather data displayed with icon
๐Ÿ“– Code Walkthrough โ€” Display Logic
lat, lon = get_coordinates(location)
Line 3: Call the Geopy function from Step 3. Returns two floats.
coords = f”{lat},{lon}”
Line 4: Format the coordinates as a single string "lat,lon" โ€” the format weather.gov expects in the URL.
fetch_weather_data(coords)
Line 5: Call the scraping function from Step 2. Returns three strings: temperature, humidity, conditions.
try / except
Lines 2โ€“8: Wrap everything in a try/except. If the user types a city Geopy can’t find, or weather.gov is down, we print a friendly error instead of crashing.
if “rain” in conditions.lower()
Lines 19โ€“25: Convert the conditions to lowercase and check for keywords. Print the matching emoji.
Going further: In a real Tkinter app, instead of print() you’d update the display label created in Step 4 with display.config(text=f"Temperature: {temperature}\nHumidity: {humidity}\n{icon}"). The print version here keeps the example simple and runnable from any terminal.
Step 06 / Conclusion

What you built & what’s next.

Building a Location-Based Weather App in Python without relying on APIs is a challenging yet rewarding endeavor. It allows you to gain a deeper understanding of web scraping, data retrieval, and geocoding.

๐ŸŽฏ What You Learned

By completing this project, you’ve gained hands-on experience with four foundational Python skills:

  • Web scraping with requests + BeautifulSoup โ€” fetching and parsing HTML from a real website.
  • Geocoding with Geopy โ€” converting human-readable city names into machine-readable coordinates.
  • GUI development with Tkinter โ€” building a desktop interface with labels, entries, and buttons.
  • End-to-end integration โ€” connecting all the pieces into a single working application.

Moreover, it gives you full control over the data, making this project a perfect opportunity to expand your Python development skills. So, dive into the code, and may your weather app be as precise as your coding skills!

Happy coding, Love you, my lovely developers! ๐Ÿ’™

๐Ÿš€ Ideas to extend the app

  • Add a 7-day forecast by parsing more tombstone-container elements from the same page.
  • Show the weather icon inside the Tkinter window using tk.PhotoImage instead of print().
  • Save search history to a small SQLite database.
  • Add a “Use my current location” button using the geocoder library.
  • Package the app with pyinstaller into a standalone .exe file.
08 / FAQ

Frequently Asked Questions

Can I build a weather app in Python without an API key? +

Yes. By scraping the National Weather Service website with requests and BeautifulSoup, you can fetch temperature, humidity, and conditions without any API key or paid plan.

What is Geopy used for in a weather app? +

Geopy converts a location name like “Paris” or “New York” into latitude and longitude coordinates. The National Weather Service URL expects these coordinates to return the correct forecast.

Why use Tkinter for the GUI? +

Tkinter ships with Python, requires no extra installation, and is perfect for beginners building simple desktop interfaces like an entry field, a button, and a results display.

Is scraping weather.gov legal? +

The National Weather Service publishes public-domain weather data. Light, non-abusive scraping for educational use is acceptable, but always review their robots.txt and terms before deploying a production app.

Run the project
yourself.

Open a terminal, install the three libraries with one pip command, and run the file end-to-end. Or click “Copy Full Project Code” at the top of this page.

No API key4 librariesDesktop GUIFull source code
09 / Share

Share this Project

If you found this walkthrough helpful, share it with your friends and fellow developers!

Scroll to Top