diff --git a/Changelog b/Changelog
index abfff2bfab7af80569ae0759b24dda778b00bf1c..fd4b65421a3d2467f0c37c60b12e18a455a840a4 100644
--- a/Changelog
+++ b/Changelog
@@ -3,7 +3,9 @@ git HEAD
     * Add URLs for several austrian EFA services
       (pointed out by Gregor Herrmann)
     * Support EFA services which do not distinguish between scheduled
-      and realtime data (pointed out by Gregor Herrmann)
+      and realtime data (also pointed out by Gregor Herrmann)
+    * efa: Add -D/--discover option
+    * Travel::Routing::DE::EFA: Add get_efa_urls method
 
 Travel::Routing::DE::VRR 2.06 - Sat Aug 02 2014
 
diff --git a/bin/efa b/bin/efa
index fa3a309e8e305392ca4119c381f7ca044c5bf1e5..3d8a377a8f4676a166690da564611875d4703663 100755
--- a/bin/efa
+++ b/bin/efa
@@ -160,6 +160,7 @@ GetOptions(
 		bike|b
 		date|d=s
 		depart=s
+		discover|D
 		efa-url|u=s
 		exclude|e=s@
 		extended-info|E
@@ -220,6 +221,40 @@ if ( $opt->{exclude} ) {
 	$opt->{exclude} = [ split( /,/, join( ',', @{ $opt->{exclude} } ) ) ];
 }
 
+if ( $opt->{discover} ) {
+	for my $pair ( Travel::Routing::DE::EFA::get_efa_urls() ) {
+		my ( $url, $name ) = @{$pair};
+		$efa = eval {
+			Travel::Routing::DE::EFA->new(
+				efa_url => $url,
+
+				origin      => [ @from, $from_type ],
+				destination => [ @to,   $to_type ],
+				via => ( @via ? [ @via, $via_type ] : undef ),
+
+				arrival_time   => $opt->{arrive},
+				departure_time => $opt->{depart} // $opt->{time},
+				date           => $opt->{date},
+				exclude        => $opt->{exclude},
+				train_type     => $opt->{include},
+				with_bike      => $opt->{bike},
+
+				select_interchange_by => $opt->{prefer},
+				use_near_stops        => $opt->{proximity},
+				walk_speed            => $opt->{'walk-speed'},
+				max_interchanges      => $opt->{'max-change'},
+				num_results           => $opt->{'num-connections'},
+
+				lwp_options => { timeout => $opt->{timeout} },
+			);
+		};
+		if ($efa) {
+			printf( "%-55s (%s)\n", $url, $name );
+		}
+	}
+	exit 0;
+}
+
 $efa = eval {
 	Travel::Routing::DE::EFA->new(
 		efa_url => $efa_url,
@@ -344,6 +379,12 @@ Journey date
 
 Choose connections allowing to carry a bike
 
+=item B<-D>|B<--discover>
+
+Probe all known EFA entry points for the specified connection. No routes are
+returned in this case. Instead, B<efa> will print the URLs and names of all
+entry points which did not return an error.
+
 =item B<-e>|B<--exclude> I<transports>
 
 Exclude I<transports> (comma separated list).
diff --git a/lib/Travel/Routing/DE/EFA.pm b/lib/Travel/Routing/DE/EFA.pm
index 931b63407c95419e9dc75cda412de5c7f66ee4d2..149dc8e6f7e725c7ebfe930fbfccf9f69e9df1df 100644
--- a/lib/Travel/Routing/DE/EFA.pm
+++ b/lib/Travel/Routing/DE/EFA.pm
@@ -742,6 +742,45 @@ sub routes {
 	return @{ $self->{routes} };
 }
 
+# static
+sub get_efa_urls {
+	return (
+		[
+			'http://efa.ivb.at/ivb/XSLT_TRIP_REQUEST2',
+			'Innsbrucker Verkehsbetriebe'
+		],
+		[
+			'http://efa.svv-info.at/sbs/XSLT_TRIP_REQUEST2',
+			'Salzburger Verkehrsverbund'
+		],
+		[
+			'http://efa.vor.at/wvb/XSLT_TRIP_REQUEST2',
+			'Verkehrsverbund Ost-Region'
+		],
+		[
+			'http://efaneu.vmobil.at/vvv/XSLT_TRIP_REQUEST2',
+			'Vorarlberger Verkehrsverbund'
+		],
+		[
+			'http://fahrplan.verbundlinie.at/stv/XSLT_TRIP_REQUEST2',
+			'Verkehsverbund Steiermark'
+		],
+		[ 'http://www.linzag.at/static/XSLT_TRIP_REQUEST2', 'Linz AG' ],
+		[
+			'http://212.114.197.7/vgnExt_oeffi/XML_TRIP_REQUEST2',
+			'Verkehrsverbund Grossraum Nuernberb'
+		],
+		[
+			'http://efa.vrr.de/vrr/XSLT_TRIP_REQUEST2',
+			'Verkehrsverbund Rhein-Ruhr'
+		],
+		[
+			'http://www2.vvs.de/vvs/XSLT_TRIP_REQUEST2',
+			'Verkehrsverbund Stuttgart'
+		],
+	);
+}
+
 1;
 
 __END__
@@ -957,6 +996,18 @@ The following methods act like the arguments to B<new>. See there.
 
 =back
 
+=head2 STATIC METHODS
+
+=over
+
+=item Travel::Status::DE::VRR::get_efa_urls()
+
+Returns a list of known EFA entry points. Each list element is a reference to
+an array consisting of two strings. The first one is the URL (as passed to
+B<efa_url>), the second describes the entity to which this URL belongs.
+
+=back
+
 =head1 DIAGNOSTICS
 
 When encountering an error, Travel::Routing::DE::EFA throws a