diff --git src/wp-admin/includes/class-wp-community-events.php src/wp-admin/includes/class-wp-community-events.php
index 053d92db1a..7f6d331190 100644
--- src/wp-admin/includes/class-wp-community-events.php
+++ src/wp-admin/includes/class-wp-community-events.php
@@ -224,7 +224,7 @@ class WP_Community_Events {
 	 *                      or false on failure.
 	 */
 	public static function get_unsafe_client_ip() {
-		$client_ip = false;
+		$client_ip = $netmask = false;
 
 		// In order of preference, with the best ones for this purpose first.
 		$address_headers = array(
@@ -251,14 +251,19 @@ class WP_Community_Events {
 			}
 		}
 
-		// These functions are not available on Windows until PHP 5.3.
-		if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
-			if ( 4 === strlen( inet_pton( $client_ip ) ) ) {
-				$netmask = '255.255.255.0'; // ipv4.
-			} else {
-				$netmask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; // ipv6.
-			}
+		$address_format = self::detect_ip_address_format( (string) $client_ip );
+		if ( ! $address_format ) {
+			$client_ip = false;
+		}
 
+		if ( $client_ip ) {
+			$client_ip = self::strip_port_from_ip_address( $client_ip, $address_format );
+			$netmask   = 4 === $address_format ? '255.255.255.0' : 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
+		}
+
+		// Partially anonymize the IP by reducing it to the corresponding network ID
+		// These functions are not available on Windows until PHP 5.3.
+		if ( $client_ip && $netmask && function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
 			$client_ip = inet_ntop( inet_pton( $client_ip ) & inet_pton( $netmask ) );
 		}
 
@@ -266,6 +271,56 @@ class WP_Community_Events {
 	}
 
 	/**
+	 * Detect the format of an IP address.
+	 *
+	 * `filter_var()` is avoided because it can be disabled in PHP builds, and
+	 * `WP_Http::is_ip_address()` is avoided because it will return false if the address
+	 * contains a port number.
+	 *
+	 * A valid IPv6 address must have at least two colons (because
+	 * addresses like `0:0:0:0:0:0:0:0` can be reduced to `::`). It can contain a valid
+	 * IPv4 address incompatibility mode (e.g., ::ffff:10.10.1.1).
+	 * A valid IPv4 address must have exactly 3 periods and at most 1 colon.
+	 *
+	 * @param string $address
+	 *
+	 * @return false|int todo document false if couldn't determine (probably not valid ip), 4, 6
+	 */
+	protected static function detect_ip_address_format( $address ) {
+		$format = false;
+
+		if ( substr_count( $address, ':' ) > 1 ) {
+			$format = 6;
+		} elseif ( 3 === substr_count( $address, '.' ) ) {
+			$format = 4;
+		}
+
+		return $format;
+	}
+
+
+	// todo document
+	protected static function strip_port_from_ip_address( $ip_address, $address_format ) {
+		if ( 4 === $address_format ) {
+			$port_delimiter = strpos( $ip_address, ':' );
+
+			if ( false !== $port_delimiter ) {
+				$ip_address = substr( $ip_address, 0, $port_delimiter );
+			}
+		} elseif ( 6 === $address_format ) {
+			$port_delimiter = strpos( $ip_address, ']' );
+
+			if ( false !== $port_delimiter ) {
+				$ip_address = substr( $ip_address, 1, $port_delimiter - 1 );
+				// todo verify it always has the brackets when there's a port
+			}
+		}
+
+		return $ip_address;
+	}
+
+
+	/**
 	 * Test if two pairs of latitude/longitude coordinates match each other.
 	 *
 	 * @since 4.8.0
diff --git tests/phpunit/tests/admin/includesCommunityEvents.php tests/phpunit/tests/admin/includesCommunityEvents.php
index ed5cc2caee..fefd4a4822 100644
--- tests/phpunit/tests/admin/includesCommunityEvents.php
+++ tests/phpunit/tests/admin/includesCommunityEvents.php
@@ -255,4 +255,37 @@ class Test_WP_Community_Events extends WP_UnitTestCase {
 			'filename' => '',
 		);
 	}
+
+	/**
+	 * Test that get_unsafe_client_ip() properly anonymizes all possible address formats
+	 *
+	 * @ticket 41083
+	 * @since 4.8.1
+	 */
+	public function test_get_unsafe_client_ip_anonymization() {
+		// todo cases that are commented out are failing and need to be fixed
+
+		$test_cases = array(
+			''                                         => false,                    // Invalid IP.
+			'unknown'                                  => false,                    // Invalid IP. Sometimes proxies add things like this, or other arbitrary strings.
+			'10.20.30.45'                              => '10.20.30.0',             // IPv4, no port
+			'10.20.30.45:20000'                        => '10.20.30.0',             // IPv4, port
+			'2a03:2880:2110:df07:face:b00c::1'         => '2a03:2880:2110:df07::',  // IPv6, no port
+			'[2a03:2880:2110:df07:face:b00c::1]:20000' => '2a03:2880:2110:df07::',  // IPv6, port
+			'0000:0000:0000:0000:0000:0000:0000:0001'  => '::',                     // IPv6, no port, reducible representation
+			'::'                                       => '::',                     // IPv6, no port, reduced representation
+			'::1'                                      => '::',                     // IPv6, no port, reduced representation
+			'[::]:20000'                               => '::',                     // IPv6, port, reduced representation
+			'[::1]'                                    => '::',                     // IPv6, address brackets without port delimiter and number, reduced representation
+			//'::127.0.0.1'                              => '::127.0.0.0',            // IPv6, no port, compatibility mode
+			//'[::ffff:10.10.1.1]:30000'                 => '::ffff:10.10.1.0',       // IPv6, port, compatibility mode
+		);
+
+		foreach ( $test_cases as $raw_ip => $expected_result ) {
+			$_SERVER['REMOTE_ADDR'] = $raw_ip;
+			$actual_result          = WP_Community_Events::get_unsafe_client_ip();
+
+			$this->assertEquals( $expected_result, $actual_result );
+		}
+	}
 }
