diff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp
index 363d034..d7c32a1 100644
--- a/src/libcamera/ipa_proxy.cpp
+++ b/src/libcamera/ipa_proxy.cpp
@@ -9,7 +9,9 @@
 
 #include <string.h>
 #include <unistd.h>
-
+#include <dlfcn.h>
+#include <elf.h>
+#include <link.h>
 #include "log.h"
 #include "utils.h"
 
@@ -20,6 +22,35 @@
  * \brief IPA Proxy
  */
 
+static bool isLibcameraInstalled()
+{
+	/* musl doesn't declare _DYNAMIC in link.h, declare it manually. */
+	extern ElfW(Dyn) _DYNAMIC[];
+
+	/*
+	 * DT_RUNPATH (DT_RPATH when the linker uses old dtags) is removed on
+	 * install.
+	 */
+	for (const ElfW(Dyn) *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) {
+		if (dyn->d_tag == DT_RUNPATH || dyn->d_tag == DT_RPATH)
+			return false;
+	}
+
+	return true;
+}
+
+static std::string libcameraPath()
+{
+	Dl_info info;
+
+	/* Look up our own symbol. */
+	int ret = dladdr(reinterpret_cast<void *>(libcameraPath), &info);
+	if (ret == 0)
+		return nullptr;
+
+	return info.dli_fname;
+}
+
 namespace libcamera {
 
 LOG_DEFINE_CATEGORY(IPAProxy)
@@ -89,10 +120,23 @@ std::string IPAProxy::resolvePath(const std::string &file) const
 		}
 	}
 
-	/*Try finding the exec target from the install directory.*/
-        std::string proxyPath = std::string(IPA_PROXY_DIR) + proxyFile;
-        if (!access(proxyPath.c_str(), X_OK))
-                return proxyPath;
+	/*
+	 *When libcamera is used before it is installed, load proxies from the
+	 *same build directory as the libcamera directory itself. This requires
+	 *identifying the path of the libcamera.so, and referencing a relative
+	 *path for the proxies from that point.
+	 */
+	if (!isLibcameraInstalled()){
+		std::string ipaProxyDir = utils::dirname(libcameraPath()) + "/../../proxy";
+
+		LOG(IPAProxy, Info)
+			<< "libcamera is not installed. Adding '"
+			<< ipaProxyDir << "' to the Proxy search path";
+
+		std::string proxyPath = ipaProxyDir + proxyFile;
+		if (!access(proxyPath.c_str(), X_OK))
+			return proxyPath;
+	}
 
 	return std::string();
 }
