I have tried and tried.
What could work- is if I could get a scrape of this page and all of the columns you can toggle on:
Network-wide->Clients
One of the columns is "Connected To."
I have been able to get decent data with this code below (also posted at Merakicode/ClientScrape at main · jadexing/Merakicode (github.com))
I also was able to pull a really nice client scrape (also on GitHub)- but none of that data shows which AP a client is connected. The goal is to choose a network, then an AP, and see the active connected clients.
HELP! (& thank you).
#This is an attempt at scraping the Meraki page Network-wide--> Clients
#This does not capture all columns, yet. This is WIP - but is solid, "As-Is."
# https://jamiegprice.substack.com/
import requests
import pandas as pd
from datetime import datetime
import time
def get_api_key():
return input("Please enter your Meraki API key: ")
def get_organizations(api_key):
url = "https://api.meraki.com/api/v1/organizations"
headers = {"X-Cisco-Meraki-API-Key": api_key}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
def get_networks(api_key, org_id):
url = f"https://api.meraki.com/api/v1/organizations/{org_id}/networks"
headers = {"X-Cisco-Meraki-API-Key": api_key}
response = requests.get(url, headers=headers)
response.raise_for_status()
networks = response.json()
sorted_networks = sorted(networks, key=lambda x: x['name']) # Sort networks alphabetically by name
return sorted_networks
def get_network_clients(api_key, network_id):
url = f"https://api.meraki.com/api/v1/networks/{network_id}/clients"
headers = {"X-Cisco-Meraki-API-Key": api_key}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
if __name__ == "__main__":
start_time = time.time()
try:
api_key = get_api_key()
organizations = get_organizations(api_key)
print("Numbered list of organizations:")
for idx, org in enumerate(organizations, 1):
print(f"{idx}. {org['name']}")
org_choice = int(input("Please enter the number of the organization you want to choose: "))
selected_org_id = organizations[org_choice - 1]['id']
networks = get_networks(api_key, selected_org_id)
print("Numbered list of networks:")
for idx, network in enumerate(networks, 1):
print(f"{idx}. {network['name']}")
network_choice = int(input("Please enter the number of the network you want to check clients for: "))
selected_network_id = networks[network_choice - 1]['id']
print("Fetching online wireless clients...")
network_clients = get_network_clients(api_key, selected_network_id)
print("List of online wireless clients:")
all_clients_data = []
for client in network_clients:
client_data = {
'Client Name': client.get('description', 'None'),
'MAC Address': client.get('mac', 'None'),
'IP Address': client.get('ip', 'None'),
'Status': client.get('status', 'None'),
'Manufacturer': client.get('manufacturer', 'None'),
'OS': client.get('os', 'None'),
'Usage (MB)': client['usage']['sent'] + client['usage']['recv'] if 'usage' in client else 'None',
'First Seen': client.get('firstSeen', 'None'), # No need to convert to timestamp here
'Last Seen': client.get('lastSeen', 'None'),
'SSID': client.get('ssid', 'None'),
'VLAN': client.get('vlan', 'None'),
'Hostname': client.get('dhcpHostname', 'None'),
'Access Point': client.get('apMac', 'None'),
'Switch Port': client.get('switchport', 'None'),
'User': client.get('user', 'None')
}
all_clients_data.append(client_data)
# Save data to a CSV file with today's date and time in the filename
now = datetime.now()
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
csv_filename = f"online_wireless_clients_{date_time}.csv"
df = pd.DataFrame(all_clients_data).fillna("None")
df.to_csv(csv_filename, index=False)
print(f"Online wireless client data has been saved to {csv_filename}.")
end_time = time.time()
runtime_minutes = (end_time - start_time) // 60
runtime_seconds = (end_time - start_time) % 60
print(f"Runtime: {int(runtime_minutes)} minutes {int(runtime_seconds)} seconds")
except requests.exceptions.HTTPError as errh:
print("Http Error:", errh)
except requests.exceptions.ConnectionError as errc:
print("Error Connecting:", errc)
except requests.exceptions.Timeout as errt:
print("Timeout Error:", errt)
except requests.exceptions.RequestException as err:
print("Oops: Something Else", err)