<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Seovoro</title>
    <description>The latest articles on DEV Community by Seovoro (@seovoro-seo).</description>
    <link>https://dev.to/seovoro-seo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4164917%2F95254ef3-b766-4c0a-80a8-557f5f5139aa.png</url>
      <title>DEV Community: Seovoro</title>
      <link>https://dev.to/seovoro-seo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seovoro-seo"/>
    <language>en</language>
    <item>
      <title>How to check a sitemap for broken links (with a short Python script)</title>
      <dc:creator>Seovoro</dc:creator>
      <pubDate>Tue, 13 Oct 2026 11:27:44 +0000</pubDate>
      <link>https://dev.to/seovoro-seo/how-to-check-a-sitemap-for-broken-links-with-a-short-python-script-1h5o</link>
      <guid>https://dev.to/seovoro-seo/how-to-check-a-sitemap-for-broken-links-with-a-short-python-script-1h5o</guid>
      <description>&lt;p&gt;Your XML sitemap is a list of pages you want search engines to crawl. If it contains pages that no longer exist, pages that redirect, or pages you have blocked, it stops being a clean list. Here is a quick way to check yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should be in a sitemap
&lt;/h2&gt;

&lt;p&gt;Only canonical pages that return a normal &lt;code&gt;200&lt;/code&gt; status and that you want in search results. Leave out &lt;code&gt;404&lt;/code&gt; and &lt;code&gt;410&lt;/code&gt; pages, redirected URLs, pages with &lt;code&gt;noindex&lt;/code&gt;, pages blocked in robots.txt and duplicate versions of the same page. One sitemap file can hold up to 50,000 URLs or 50 MB uncompressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: list every URL
&lt;/h2&gt;

&lt;p&gt;Open the sitemap, or use a tool that extracts the URLs. If you use a sitemap index, remember that it points to other sitemap files, so you need to read those too. The script below does that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: check the status of each URL
&lt;/h2&gt;

&lt;p&gt;This script reads a sitemap (or a sitemap index), then asks each URL for its status without following redirects. Only run it on your own site, or with permission, and keep the delay so you do not overload the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;

&lt;span class="n"&gt;SITEMAP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/sitemap.xml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;NS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://www.sitemaps.org/schemas/sitemap/0.9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;urls_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sitemap_url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sitemap_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sitemapindex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;loc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sm:sitemap/sm:loc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nf"&gt;urls_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;loc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sm:url/sm:loc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;urls_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SITEMAP&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_redirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything printed is a URL that does not return a plain &lt;code&gt;200&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: decide what to do
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Page works&lt;/td&gt;
&lt;td&gt;Keep it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;301 or 308&lt;/td&gt;
&lt;td&gt;Moved permanently&lt;/td&gt;
&lt;td&gt;Put the final address in the sitemap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;302, 303 or 307&lt;/td&gt;
&lt;td&gt;Temporary move&lt;/td&gt;
&lt;td&gt;Check whether it should be permanent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404 or 410&lt;/td&gt;
&lt;td&gt;Page is gone&lt;/td&gt;
&lt;td&gt;Remove it, or restore the page if it should exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5xx&lt;/td&gt;
&lt;td&gt;Server error&lt;/td&gt;
&lt;td&gt;Fix the server problem and check again&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 4: update and resubmit
&lt;/h2&gt;

&lt;p&gt;Remove or replace the bad URLs, upload the new sitemap and submit it again in Google Search Console. Google Search Console's Pages report also lists problems such as "Submitted URL not found (404)", so check it too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it clean
&lt;/h2&gt;

&lt;p&gt;Generate the sitemap automatically so deleted pages drop out of it, and run this check after every redesign or migration.&lt;/p&gt;

&lt;p&gt;If you want a no-code version, our free &lt;a href="https://seovoro.com/tools/sitemap-url-extractor.php" rel="noopener noreferrer"&gt;Sitemap URL Extractor&lt;/a&gt; lists every URL in a sitemap, and the &lt;a href="https://seovoro.com/tools/sitemap-validator.php" rel="noopener noreferrer"&gt;Sitemap Validator&lt;/a&gt; checks the file itself. The full guide, with more detail, is on &lt;a href="https://seovoro.com/single-blog.php?slug=how-to-check-a-sitemap-for-broken-links" rel="noopener noreferrer"&gt;seovoro.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How We Improved Our Website's Mobile PageSpeed Score From 81 to 100</title>
      <dc:creator>Seovoro</dc:creator>
      <pubDate>Mon, 05 Oct 2026 22:02:09 +0000</pubDate>
      <link>https://dev.to/seovoro-seo/how-we-improved-our-websites-mobile-pagespeed-score-from-81-to-100-3e03</link>
      <guid>https://dev.to/seovoro-seo/how-we-improved-our-websites-mobile-pagespeed-score-from-81-to-100-3e03</guid>
      <description>&lt;p&gt;Website performance matters for both users and search engines.&lt;/p&gt;

&lt;p&gt;We recently worked on our own website and improved its mobile PageSpeed score from 81 to 100.&lt;/p&gt;

&lt;p&gt;Instead of simply sharing the final score, we wanted to document what we changed, what caused the performance issues, and what the results looked like afterward.&lt;/p&gt;

&lt;p&gt;The Starting Point&lt;br&gt;
Before making the changes, our mobile PageSpeed score was:&lt;/p&gt;

&lt;p&gt;81 / 100&lt;/p&gt;

&lt;p&gt;The website was functional, but there was still room for improvement.&lt;/p&gt;

&lt;p&gt;We checked the PageSpeed Insights report to identify which resources and page elements were contributing to the performance issues.&lt;/p&gt;

&lt;p&gt;The goal wasn't to blindly optimize everything. We wanted to identify the actual bottlenecks and make targeted changes.&lt;/p&gt;

&lt;p&gt;What We Changed&lt;br&gt;
We focused on several areas that commonly affect website performance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reduced unnecessary resources
We reviewed the CSS and JavaScript being loaded on the page and removed or reduced resources that weren't necessary for the initial page load.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This helped reduce the amount of work the browser needed to perform before the page became usable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Optimized images
Large images can have a significant effect on mobile performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We reviewed the images used on the page and optimized them so the browser didn't have to download unnecessarily large files.&lt;/p&gt;

&lt;p&gt;We also paid attention to how images were loaded so that they wouldn't interfere with the initial rendering of the page.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Improved CSS delivery
We reviewed our CSS and reduced unnecessary styling and resources that were being loaded before the main content could render.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The objective was to make the critical part of the page available to the browser as quickly as possible.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reduced unnecessary page overhead
We also reviewed the HTML structure and other elements that weren't contributing directly to the user experience.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Small improvements across several areas can add up to a noticeable performance difference.&lt;/p&gt;

&lt;p&gt;The Result&lt;br&gt;
After making the changes, we ran the page through Google PageSpeed Insights again.&lt;/p&gt;

&lt;p&gt;The mobile score improved from:&lt;/p&gt;

&lt;p&gt;81 → 100&lt;/p&gt;

&lt;p&gt;The final report also showed improved performance metrics compared with the original test.&lt;/p&gt;

&lt;p&gt;The important point is that the improvement didn't come from one magic optimization.&lt;/p&gt;

&lt;p&gt;It came from identifying several smaller performance problems and addressing them systematically.&lt;/p&gt;

&lt;p&gt;Before and After&lt;br&gt;
Before: Mobile PageSpeed — 81&lt;/p&gt;

&lt;p&gt;After: Mobile PageSpeed — 100&lt;/p&gt;

&lt;p&gt;We captured screenshots of both tests as well as the final performance metrics so the results can be independently reviewed.&lt;/p&gt;

&lt;p&gt;What We Learned&lt;br&gt;
One of the biggest lessons from this process is that website performance optimization should be based on measurements rather than assumptions.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;p&gt;"What optimization should we try?"&lt;br&gt;
It's usually better to ask:&lt;/p&gt;

&lt;p&gt;"What is the performance report actually telling us?"&lt;br&gt;
That approach makes it easier to prioritize the changes that are most likely to have an impact.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;br&gt;
Measure performance before making changes.&lt;br&gt;
Optimize images and other large resources.&lt;br&gt;
Reduce unnecessary CSS and JavaScript.&lt;br&gt;
Pay attention to what blocks the initial rendering.&lt;br&gt;
Test again after every major optimization.&lt;br&gt;
Don't rely on a single optimization to solve every performance issue.&lt;br&gt;
Keep real before-and-after measurements.&lt;br&gt;
One Important Limitation&lt;br&gt;
A PageSpeed score is useful, but it isn't the entire story.&lt;/p&gt;

&lt;p&gt;Real users can have different devices, network conditions, browsers, and geographic locations.&lt;/p&gt;

&lt;p&gt;A perfect lab score doesn't automatically mean every visitor will experience a perfect website.&lt;/p&gt;

&lt;p&gt;That's why performance should be treated as an ongoing process rather than a one-time task.&lt;/p&gt;

&lt;p&gt;Full Case Study&lt;br&gt;
We've published the complete case study on our website, including the detailed before-and-after results, screenshots, metrics, and the changes we made:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://seovoro.com/single-blog.php?slug=case-study-mobile-pagespeed-81-to-100" rel="noopener noreferrer"&gt;https://seovoro.com/single-blog.php?slug=case-study-mobile-pagespeed-81-to-100&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're working on website performance yourself, hopefully this breakdown gives you a useful starting point.&lt;/p&gt;

&lt;p&gt;About Seovoro&lt;/p&gt;

&lt;p&gt;Seovoro helps businesses improve their organic search visibility through SEO, technical optimization, content, local SEO, and AI-search strategies.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://seovoro.com" rel="noopener noreferrer"&gt;https://seovoro.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>performance</category>
      <category>php</category>
    </item>
  </channel>
</rss>
