diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts
index b2166c34..fe2ea62b 100644
--- a/src/backend/metadata/getmeta.ts
+++ b/src/backend/metadata/getmeta.ts
@@ -8,6 +8,7 @@ import {
   getExternalIds,
   getMediaDetails,
   getMediaPoster,
+  getMovieFromExternalId,
   mediaTypeToTMDB,
 } from "./tmdb";
 import {
@@ -206,11 +207,23 @@ export async function convertLegacyUrl(
   if (url.startsWith("/media/JW")) {
     const urlParts = url.split("/").slice(2);
     const [, type, id] = urlParts[0].split("-", 3);
-    const meta = await getLegacyMetaFromId(TMDBMediaToMediaType(type), id);
+
+    const mediaType = TMDBMediaToMediaType(type);
+    const meta = await getLegacyMetaFromId(mediaType, id);
+
     if (!meta) return undefined;
-    const tmdbId = meta.tmdbId;
-    if (!tmdbId) return undefined;
-    return `/media/tmdb-${type}-${tmdbId}`;
+    const { tmdbId, imdbId } = meta;
+    if (!tmdbId && !imdbId) return undefined;
+
+    // movies always have an imdb id on tmdb
+    if (imdbId && mediaType === MWMediaType.MOVIE) {
+      const movieId = await getMovieFromExternalId(imdbId);
+      if (movieId) return `/media/tmdb-movie-${movieId}`;
+    }
+
+    if (tmdbId) {
+      return `/media/tmdb-${type}-${tmdbId}`;
+    }
   }
   return undefined;
 }
diff --git a/src/backend/metadata/tmdb.ts b/src/backend/metadata/tmdb.ts
index f5d1e370..db665528 100644
--- a/src/backend/metadata/tmdb.ts
+++ b/src/backend/metadata/tmdb.ts
@@ -2,6 +2,7 @@ import { conf } from "@/setup/config";
 
 import { MWMediaMeta, MWMediaType, MWSeasonMeta } from "./types/mw";
 import {
+  ExternalIdMovieSearchResult,
   TMDBContentTypes,
   TMDBEpisodeShort,
   TMDBExternalIds,
@@ -195,6 +196,19 @@ export async function getExternalIds(
   return data;
 }
 
+export async function getMovieFromExternalId(
+  imdbId: string
+): Promise<string | undefined> {
+  const data = await get<ExternalIdMovieSearchResult>(`/find/${imdbId}`, {
+    external_source: "imdb_id",
+  });
+
+  const movie = data.movie_results[0];
+  if (!movie) return undefined;
+
+  return movie.id.toString();
+}
+
 export function formatTMDBSearchResult(
   result: TMDBShowResult | TMDBMovieResult,
   mediatype: TMDBContentTypes
diff --git a/src/backend/metadata/types/tmdb.ts b/src/backend/metadata/types/tmdb.ts
index cb5e9aa4..843786f4 100644
--- a/src/backend/metadata/types/tmdb.ts
+++ b/src/backend/metadata/types/tmdb.ts
@@ -282,3 +282,27 @@ export interface TMDBMovieExternalIds {
 }
 
 export type TMDBExternalIds = TMDBShowExternalIds | TMDBMovieExternalIds;
+
+export interface ExternalIdMovieSearchResult {
+  movie_results: {
+    adult: boolean;
+    backdrop_path: string;
+    id: number;
+    title: string;
+    original_language: string;
+    original_title: string;
+    overview: string;
+    poster_path: string;
+    media_type: string;
+    genre_ids: number[];
+    popularity: number;
+    release_date: string;
+    video: boolean;
+    vote_average: number;
+    vote_count: number;
+  }[];
+  person_results: any[];
+  tv_results: any[];
+  tv_episode_results: any[];
+  tv_season_results: any[];
+}
diff --git a/src/setup/App.tsx b/src/setup/App.tsx
index d0a0887f..0516eb48 100644
--- a/src/setup/App.tsx
+++ b/src/setup/App.tsx
@@ -1,11 +1,5 @@
-import { lazy } from "react";
-import {
-  Redirect,
-  Route,
-  Switch,
-  useHistory,
-  useLocation,
-} from "react-router-dom";
+import { lazy, useEffect, useState } from "react";
+import { Redirect, Route, Switch, useLocation } from "react-router-dom";
 
 import { convertLegacyUrl } from "@/backend/metadata/getmeta";
 import { MWMediaType } from "@/backend/metadata/types/mw";
@@ -19,86 +13,105 @@ import { NotFoundPage } from "@/views/notfound/NotFoundView";
 import { V2MigrationView } from "@/views/other/v2Migration";
 import { SearchView } from "@/views/search/SearchView";
 
-function App() {
+// eslint-disable-next-line react/function-component-definition, react/prop-types
+const LegacyUrlView: React.FC = ({ children }) => {
   const location = useLocation();
-  const history = useHistory();
+  const [redirectUrl, setRedirectUrl] = useState<string | null>(null);
 
-  // Call the conversion function and redirect if necessary
-  convertLegacyUrl(location.pathname).then((convertedUrl) => {
-    if (convertedUrl) {
-      history.replace(convertedUrl);
-    }
-  });
+  useEffect(() => {
+    // Call the conversion function and set the redirect URL if necessary
+    convertLegacyUrl(location.pathname).then((convertedUrl) => {
+      if (convertedUrl) {
+        setRedirectUrl(convertedUrl);
+      }
+    });
+  }, [location.pathname]);
+
+  if (redirectUrl) {
+    return <Redirect to={redirectUrl} />;
+  }
+
+  // eslint-disable-next-line react/jsx-no-useless-fragment
+  return <>{children}</>;
+};
+
+function App() {
   return (
     <SettingsProvider>
       <WatchedContextProvider>
         <BookmarkContextProvider>
           <BannerContextProvider>
             <Layout>
-              <Switch>
-                {/* functional routes */}
-                <Route exact path="/v2-migration" component={V2MigrationView} />
-                <Route exact path="/">
-                  <Redirect to={`/search/${MWMediaType.MOVIE}`} />
-                </Route>
+              <LegacyUrlView>
+                <Switch>
+                  {/* functional routes */}
+                  <Route
+                    exact
+                    path="/v2-migration"
+                    component={V2MigrationView}
+                  />
+                  <Route exact path="/">
+                    <Redirect to={`/search/${MWMediaType.MOVIE}`} />
+                  </Route>
 
-                {/* pages */}
-                <Route exact path="/media/:media" component={MediaView} />
-                <Route
-                  exact
-                  path="/media/:media/:season/:episode"
-                  component={MediaView}
-                />
-                <Route
-                  exact
-                  path="/search/:type/:query?"
-                  component={SearchView}
-                />
+                  {/* pages */}
+                  <Route exact path="/media/:media" component={MediaView} />
+                  <Route
+                    exact
+                    path="/media/:media/:season/:episode"
+                    component={MediaView}
+                  />
+                  <Route
+                    exact
+                    path="/search/:type/:query?"
+                    component={SearchView}
+                  />
 
-                {/* other */}
-                <Route
-                  exact
-                  path="/dev"
-                  component={lazy(
-                    () => import("@/views/developer/DeveloperView")
-                  )}
-                />
-                <Route
-                  exact
-                  path="/dev/video"
-                  component={lazy(
-                    () => import("@/views/developer/VideoTesterView")
-                  )}
-                />
-                {/* developer routes that can abuse workers are disabled in production */}
-                {process.env.NODE_ENV === "development" ? (
-                  <>
-                    <Route
-                      exact
-                      path="/dev/test"
-                      component={lazy(
-                        () => import("@/views/developer/TestView")
-                      )}
-                    />
+                  {/* other */}
+                  <Route
+                    exact
+                    path="/dev"
+                    component={lazy(
+                      () => import("@/views/developer/DeveloperView")
+                    )}
+                  />
+                  <Route
+                    exact
+                    path="/dev/video"
+                    component={lazy(
+                      () => import("@/views/developer/VideoTesterView")
+                    )}
+                  />
+                  {/* developer routes that can abuse workers are disabled in production */}
+                  {process.env.NODE_ENV === "development" ? (
+                    <>
+                      <Route
+                        exact
+                        path="/dev/test"
+                        component={lazy(
+                          () => import("@/views/developer/TestView")
+                        )}
+                      />
 
-                    <Route
-                      exact
-                      path="/dev/providers"
-                      component={lazy(
-                        () => import("@/views/developer/ProviderTesterView")
-                      )}
-                    />
-                    <Route
-                      exact
-                      path="/dev/embeds"
-                      component={lazy(
-                        () => import("@/views/developer/EmbedTesterView")
-                      )}
-                    />
-                  </>
-                ) : null}
-                <Route path="*" component={NotFoundPage} />
-              </Switch>
+                      <Route
+                        exact
+                        path="/dev/providers"
+                        component={lazy(
+                          () => import("@/views/developer/ProviderTesterView")
+                        )}
+                      />
+                      <Route
+                        exact
+                        path="/dev/embeds"
+                        component={lazy(
+                          () => import("@/views/developer/EmbedTesterView")
+                        )}
+                      />
+                    </>
+                  ) : null}
+                  <Route path="*" component={NotFoundPage} />
+                </Switch>
+              </LegacyUrlView>
             </Layout>
           </BannerContextProvider>
         </BookmarkContextProvider>