Ping Test to Popular Websites

First, we define the webiste to ping. This is collection of popular websites + some Indonesian websites.
Show code (37 lines)
websites = [
    'google.com',
    'facebook.com', 
    'apple.com',
    'amazon.com',
    'microsoft.com',
    'netflix.com',
    'twitter.com',
    'instagram.com',
    'linkedin.com',
    'youtube.com',
    'reddit.com',
    'wikipedia.org',
    'github.com',
    'yahoo.com',
    'twitch.tv',
    'tiktok.com',
    'spotify.com',
    'whatsapp.com',
    'zoom.us',
    'discord.com',
    'pinterest.com',
    'dropbox.com',
    'salesforce.com',
    'tokopedia.com',
    'shopee.co.id',
    'zalora.co.id',
    'lazada.co.id',
    'bukalapak.com',
    'blibli.com',
    'kompas.com',
    'detik.com',
    'tribunnews.com',
    'cnbcindonesia.com',
    'okezone.com',
    'liputan6.com',
]
We then define the function to ping the website. Will use the ping command.
Show code (42 lines)
import subprocess

def ping_website(website):
    try:
        result = subprocess.run(['ping', '-c', '10', website], 
                              capture_output=True, 
                              text=True,
                              timeout=10)
        
        if result.returncode == 0:
            # Get IP address from first line
            first_line = result.stdout.split('\n')[0]
            ip_address = first_line.split('(')[1].split(')')[0]
            
            # Get all ping times
            ping_times = []
            for line in result.stdout.split('\n')[1:-5]: # Skip first and last summary lines
                if 'bytes from' in line:
                    time = float(line.split('time=')[1].split()[0])
                    ping_times.append(time)
                    
            status = 'Success'
        else:
            ip_address = None
            ping_times = []
            status = 'Failed'
            
    except subprocess.TimeoutExpired:
        ip_address = None
        ping_times = []
        status = 'Timeout'
    except Exception as e:
        ip_address = None
        ping_times = []
        status = f'Error: {str(e)}'
        
    return {
        'website': website,
        'ip_address': ip_address,
        'status': status,
        'ping_times_ms': ping_times
    }
Then we ping all websites. Do it in parallel so it don’t take much time.
import pandas as pd
import concurrent.futures

results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    future_to_website = {executor.submit(ping_website, website): website for website in websites}
    for future in concurrent.futures.as_completed(future_to_website):
        result = future.result()
        results.append(result)

df = pd.DataFrame(results)

There are some websites that failed to ping. It is probably because the website is blocking ICMP ping requests as a security measure.

We can see this in the data where some entries have status=‘Failed’ or status=‘Timeout’

df[df['status'] != 'Success'][['website', 'status']]
websitestatus
7apple.comTimeout
8linkedin.comTimeout
9netflix.comTimeout
29tokopedia.comTimeout
34detik.comTimeout
Now we calculate the statistics for the successful pings so we can glance some insights.
# Calculate statistics for successful pings only
df_stats = df[df['status'] == 'Success'].copy()
df_stats['min_ms'] = df_stats['ping_times_ms'].apply(lambda x: min(x))
df_stats['max_ms'] = df_stats['ping_times_ms'].apply(lambda x: max(x))
df_stats['avg_ms'] = df_stats['ping_times_ms'].apply(lambda x: sum(x)/len(x))
df_stats['p50_ms'] = df_stats['ping_times_ms'].apply(lambda x: sorted(x)[len(x)//2])
df_stats['std_ms'] = df_stats['ping_times_ms'].apply(lambda x: pd.Series(x).std())
And chart the results.
import altair as alt
chart = alt.Chart(df_stats).mark_bar().encode(
    y=alt.Y('website:N', sort='x'),
    x=alt.X('avg_ms:Q', title='Average Ping Time (ms)'),
    tooltip=['website', 'avg_ms', 'min_ms', 'max_ms']
).properties(
    width=800,
    height=400,
    title='Average Ping Time by Website - lower is better'
)
chart

It is interesting to see that the ping latency of various websites fall under 3 ranges.

  1. Under 1-3 ms
  2. 10-15 ms
  3. 180++ ms

I am not sure why the case. There is no pattern that I can see. Whether it is international vs Indonesian websites, or the type of websites (news, e-commerce, etc).


🗒️ Download (notebook.ipynb)