Building a Free Weather Radio Scheduler for Hixson
I walk through building a Node.js service that scrapes free weather radio programming for Hixson, parses the schedule, and serves a simple API. Learn the steps and pitfalls.
I was scrolling through the local news on Thursday when I saw a note about free weather radio programming airing in Hixson. As a developer who loves turning quirky data sources into useful services, I decided to turn that bulletin into a tiny API that anyone could query for the day’s broadcast schedule. In this post I’ll show you how I fetched the raw schedule, parsed the HTML, and exposed a clean JSON endpoint with Node.js.
Why this matters: If you’re building any feature that depends on third‑party broadcast data, you need a reliable way to fetch, normalize, and serve that information without breaking your users’ experience.
#Scraping the Hixson Weather Radio Schedule
The first hurdle was locating the source. The local station publishes a simple HTML page that lists each hour’s forecast segment. Because the page isn’t an official API, we have to treat it as a web‑scraping target.
#Choosing the right HTTP client
I went with axios for its promise‑based API and built‑in timeout handling.
const axios = require('axios');
async function fetchSchedule(url) {
const response = await axios.get(url, { timeout: 5000 });
return response.data; // raw HTML
}Tip: Set a reasonable timeout (e.g., 5 seconds) to avoid hanging your service when the station’s site is down.
#Parsing the HTML with Cheerio
Once we have the raw HTML, we need to extract the time slots and descriptions. Cheerio gives us jQuery‑like selectors without a full browser.
const cheerio = require('cheerio');
function parseSchedule(html) {
const $ = cheerio.load(html);
const schedule = [];
$('.schedule-row').each((i, el) => {
const time = $(el).find('.time').text().trim();
const title = $(el).find('.title').text().trim();
schedule.push({ time, title });
});
return schedule;
}Note: The class names (
.schedule-row,.time,.title) were identified by inspecting the page source on the station’s website. If they change, your scraper will need an update.
#Exposing a Simple JSON API with Express
Now that we can turn the HTML into a JavaScript object, the next step is to serve it. I kept the API minimal: a single GET endpoint that returns the current day’s schedule.
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/hixson/weather-radio', async (req, res) => {
try {
const html = await fetchSchedule('https://local3news.com/weather-radio');
const schedule = parseSchedule(html);
res.json({ date: new Date().toISOString().split('T')[0], schedule });
} catch (err) {
console.error(err);
res.status(502).json({ error: 'Failed to retrieve schedule' });
}
});
app.listen(PORT, () => console.log(`API listening on port ${PORT}`));Warning: Never expose raw HTML or internal errors to callers; always sanitize the response and return a generic error message.
#Adding CORS for client‑side consumption
If you plan to call this endpoint from a browser, enable CORS:
const cors = require('cors');
app.use(cors({ origin: '*' }));#Deploying Serverlessly with Vercel
Running a Node server 24/7 can be overkill for a lightweight scraper. Vercel’s Serverless Functions let you deploy each endpoint as an isolated function that scales automatically.
- Move the Express handler into
api/hixson/weather-radio.js. - Export the handler as
module.exports = (req, res) => { … }. - Push to a GitHub repo linked to Vercel; the platform builds and deploys automatically.
This approach reduces operational overhead and keeps costs low—something you’ll appreciate when budgeting.
#Estimating Project Costs Early
Before you spin up any cloud resources, I like to get a quick cost projection. If you need to budget the hosting, I’ve been using Estimate Website Cost to generate AI‑powered estimates based on expected traffic and runtime minutes. The tool gave me a ballpark figure of under $5/month for the serverless setup, which fit nicely into my personal project budget.
#Handling Edge Cases and Rate Limits
Even with a simple scraper, you’ll run into quirks:
- Schedule updates at midnight: Cache the result for a few hours to avoid hammering the source.
- Unexpected HTML changes: Wrap parsing logic in a
try/catchand log the raw HTML for debugging. - Rate limiting by the station: Respect
robots.txtand add aUser-Agentheader that identifies your app.
await axios.get(url, {
headers: { 'User-Agent': 'HixsonWeatherBot/1.0 (+https://github.com/you)' },
timeout: 5000
});#Full Workflow Summary
- Discover the source – locate the public schedule page.
- Fetch the HTML – use
axioswith proper timeouts and headers. - Parse with Cheerio – extract time slots into a clean array.
- Expose via Express – create a tiny JSON API.
- Deploy serverlessly – push to Vercel for zero‑maintenance hosting.
- Budget with a cost estimator – validate that the solution stays affordable.
#Further Reading
Building this little service taught me that even hyper‑local data—like a free weather radio schedule—can become a reusable API with a few lines of code. If you follow the steps above, you’ll have a reliable endpoint for Hixson’s weather updates, and you’ll know exactly how much it will cost to keep it running. Happy coding!
Related posts
- Link to article5 min read
How to Handle Programming Schedule Changes for Radio Apps
Learn practical strategies to implement programming schedule changes in a radio streaming app, covering real‑time updates, testing edge cases, and budgeting with reliable cost estimates.
- Link to article5 min read
General Conference Special Programming: A Developer’s Guide
Learn how to architect, API‑design, and display General Conference special programming tracks. Get data‑model tips, front‑end rendering tricks, and budgeting advice with a conference schedule API.